Diff
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (220317 => 220318)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2017-08-05 11:14:34 UTC (rev 220317)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2017-08-05 14:10:07 UTC (rev 220318)
@@ -376,7 +376,6 @@
dfg/DFGOSREntry.cpp
dfg/DFGOSREntrypointCreationPhase.cpp
dfg/DFGOSRExit.cpp
- dfg/DFGOSRExit32_64.cpp
dfg/DFGOSRExitBase.cpp
dfg/DFGOSRExitCompilerCommon.cpp
dfg/DFGOSRExitFuzz.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (220317 => 220318)
--- trunk/Source/_javascript_Core/ChangeLog 2017-08-05 11:14:34 UTC (rev 220317)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-08-05 14:10:07 UTC (rev 220318)
@@ -1,3 +1,22 @@
+2017-08-05 Mark Lam <mark....@apple.com>
+
+ Move DFG::OSRExitCompiler methods into DFG::OSRExit [step 3].
+ https://bugs.webkit.org/show_bug.cgi?id=175228
+ <rdar://problem/33735737>
+
+ Reviewed by Saam Barati.
+
+ Merge the 32-bit OSRExit::compileExit() method into the 64-bit version, and
+ delete OSRExit32_64.cpp.
+
+ * CMakeLists.txt:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * dfg/DFGOSRExit.cpp:
+ (JSC::DFG::OSRExit::compileExit):
+ * dfg/DFGOSRExit32_64.cpp: Removed.
+ * jit/GPRInfo.h:
+ (JSC::JSValueSource::payloadGPR const):
+
2017-08-04 Youenn Fablet <you...@apple.com>
[Cache API] Add Cache and CacheStorage IDL definitions
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (220317 => 220318)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2017-08-05 11:14:34 UTC (rev 220317)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2017-08-05 14:10:07 UTC (rev 220318)
@@ -744,7 +744,6 @@
0FBF158C19B7A53100695DD0 /* DFGBlockSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBF158A19B7A53100695DD0 /* DFGBlockSet.cpp */; };
0FBF158D19B7A53100695DD0 /* DFGBlockSetInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBF158B19B7A53100695DD0 /* DFGBlockSetInlines.h */; };
0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC097681468A6EF00CF2442 /* DFGOSRExit.h */; };
- 0FC09776146943B000CF2442 /* DFGOSRExit32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC09775146943AD00CF2442 /* DFGOSRExit32_64.cpp */; };
0FC09791146A6F7100CF2442 /* DFGOSRExit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC0978E146A6F6300CF2442 /* DFGOSRExit.cpp */; };
0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC0979F146B28C700CF2442 /* DFGThunks.cpp */; };
0FC097A2146B28CC00CF2442 /* DFGThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC097A0146B28C700CF2442 /* DFGThunks.h */; };
@@ -3339,7 +3338,6 @@
0FBF158A19B7A53100695DD0 /* DFGBlockSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBlockSet.cpp; path = dfg/DFGBlockSet.cpp; sourceTree = "<group>"; };
0FBF158B19B7A53100695DD0 /* DFGBlockSetInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBlockSetInlines.h; path = dfg/DFGBlockSetInlines.h; sourceTree = "<group>"; };
0FC097681468A6EF00CF2442 /* DFGOSRExit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExit.h; path = dfg/DFGOSRExit.h; sourceTree = "<group>"; };
- 0FC09775146943AD00CF2442 /* DFGOSRExit32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSRExit32_64.cpp; path = dfg/DFGOSRExit32_64.cpp; sourceTree = "<group>"; };
0FC0977E1469EBC400CF2442 /* DFGCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCommon.h; path = dfg/DFGCommon.h; sourceTree = "<group>"; };
0FC0978E146A6F6300CF2442 /* DFGOSRExit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSRExit.cpp; path = dfg/DFGOSRExit.cpp; sourceTree = "<group>"; };
0FC0979F146B28C700CF2442 /* DFGThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGThunks.cpp; path = dfg/DFGThunks.cpp; sourceTree = "<group>"; };
@@ -7467,7 +7465,6 @@
0FD8A31E17D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.h */,
0FC0978E146A6F6300CF2442 /* DFGOSRExit.cpp */,
0FC097681468A6EF00CF2442 /* DFGOSRExit.h */,
- 0FC09775146943AD00CF2442 /* DFGOSRExit32_64.cpp */,
0F235BE717178E7300690C7F /* DFGOSRExitBase.cpp */,
0F235BE817178E7300690C7F /* DFGOSRExitBase.h */,
65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */,
@@ -10474,7 +10471,6 @@
0FD8A32517D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.cpp in Sources */,
0FC09791146A6F7100CF2442 /* DFGOSRExit.cpp in Sources */,
0F235BEB17178E7300690C7F /* DFGOSRExitBase.cpp in Sources */,
- 0FC09776146943B000CF2442 /* DFGOSRExit32_64.cpp in Sources */,
0F7025A91714B0FA00382C0E /* DFGOSRExitCompilerCommon.cpp in Sources */,
0F392C891B46188400844728 /* DFGOSRExitFuzz.cpp in Sources */,
0FEFC9AA1681A3B300567F53 /* DFGOSRExitJumpPlaceholder.cpp in Sources */,
Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp (220317 => 220318)
--- trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp 2017-08-05 11:14:34 UTC (rev 220317)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp 2017-08-05 14:10:07 UTC (rev 220318)
@@ -223,8 +223,6 @@
vm->osrExitJumpDestination = exit.m_code.code().executableAddress();
}
-#if USE(JSVALUE64)
-
void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const Operands<ValueRecovery>& operands, SpeculationRecovery* recovery)
{
jit.jitAssertTagsInPlace();
@@ -246,16 +244,22 @@
switch (recovery->type()) {
case SpeculativeAdd:
jit.sub32(recovery->src(), recovery->dest());
+#if USE(JSVALUE64)
jit.or64(GPRInfo::tagTypeNumberRegister, recovery->dest());
+#endif
break;
case SpeculativeAddImmediate:
jit.sub32(AssemblyHelpers::Imm32(recovery->immediate()), recovery->dest());
+#if USE(JSVALUE64)
jit.or64(GPRInfo::tagTypeNumberRegister, recovery->dest());
+#endif
break;
case BooleanSpeculationCheck:
+#if USE(JSVALUE64)
jit.xor64(AssemblyHelpers::TrustedImm32(static_cast<int32_t>(ValueFalse)), recovery->dest());
+#endif
break;
default:
@@ -278,16 +282,36 @@
CodeOrigin codeOrigin = exit.m_codeOriginForExitProfile;
if (ArrayProfile* arrayProfile = jit.baselineCodeBlockFor(codeOrigin)->getArrayProfile(codeOrigin.bytecodeIndex)) {
+#if USE(JSVALUE64)
GPRReg usedRegister;
if (exit.m_jsValueSource.isAddress())
usedRegister = exit.m_jsValueSource.base();
else
usedRegister = exit.m_jsValueSource.gpr();
+#else
+ GPRReg usedRegister1;
+ GPRReg usedRegister2;
+ if (exit.m_jsValueSource.isAddress()) {
+ usedRegister1 = exit.m_jsValueSource.base();
+ usedRegister2 = InvalidGPRReg;
+ } else {
+ usedRegister1 = exit.m_jsValueSource.payloadGPR();
+ if (exit.m_jsValueSource.hasKnownTag())
+ usedRegister2 = InvalidGPRReg;
+ else
+ usedRegister2 = exit.m_jsValueSource.tagGPR();
+ }
+#endif
GPRReg scratch1;
GPRReg scratch2;
+#if USE(JSVALUE64)
scratch1 = AssemblyHelpers::selectScratchGPR(usedRegister);
scratch2 = AssemblyHelpers::selectScratchGPR(usedRegister, scratch1);
+#else
+ scratch1 = AssemblyHelpers::selectScratchGPR(usedRegister1, usedRegister2);
+ scratch2 = AssemblyHelpers::selectScratchGPR(usedRegister1, usedRegister2, scratch1);
+#endif
if (isARM64()) {
jit.pushToSave(scratch1);
@@ -302,11 +326,15 @@
value = scratch1;
jit.loadPtr(AssemblyHelpers::Address(exit.m_jsValueSource.asAddress()), value);
} else
- value = exit.m_jsValueSource.gpr();
+ value = exit.m_jsValueSource.payloadGPR();
jit.load32(AssemblyHelpers::Address(value, JSCell::structureIDOffset()), scratch1);
jit.store32(scratch1, arrayProfile->addressOfLastSeenStructureID());
+#if USE(JSVALUE64)
jit.load8(AssemblyHelpers::Address(value, JSCell::indexingTypeAndMiscOffset()), scratch1);
+#else
+ jit.load8(AssemblyHelpers::Address(scratch1, Structure::indexingTypeIncludingHistoryOffset()), scratch1);
+#endif
jit.move(AssemblyHelpers::TrustedImm32(1), scratch2);
jit.lshift32(scratch1, scratch2);
jit.or32(scratch2, AssemblyHelpers::AbsoluteAddress(arrayProfile->addressOfArrayModes()));
@@ -322,6 +350,7 @@
}
if (MethodOfGettingAValueProfile profile = "" {
+#if USE(JSVALUE64)
if (exit.m_jsValueSource.isAddress()) {
// We can't be sure that we have a spare register. So use the tagTypeNumberRegister,
// since we know how to restore it.
@@ -330,6 +359,31 @@
jit.move(AssemblyHelpers::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister);
} else
profile.emitReportValue(jit, JSValueRegs(exit.m_jsValueSource.gpr()));
+#else // not USE(JSVALUE64)
+ if (exit.m_jsValueSource.isAddress()) {
+ // Save a register so we can use it.
+ GPRReg scratchPayload = AssemblyHelpers::selectScratchGPR(exit.m_jsValueSource.base());
+ GPRReg scratchTag = AssemblyHelpers::selectScratchGPR(exit.m_jsValueSource.base(), scratchPayload);
+ jit.pushToSave(scratchPayload);
+ jit.pushToSave(scratchTag);
+
+ JSValueRegs scratch(scratchTag, scratchPayload);
+
+ jit.loadValue(exit.m_jsValueSource.asAddress(), scratch);
+ profile.emitReportValue(jit, scratch);
+
+ jit.popToRestore(scratchTag);
+ jit.popToRestore(scratchPayload);
+ } else if (exit.m_jsValueSource.hasKnownTag()) {
+ GPRReg scratchTag = AssemblyHelpers::selectScratchGPR(exit.m_jsValueSource.payloadGPR());
+ jit.pushToSave(scratchTag);
+ jit.move(AssemblyHelpers::TrustedImm32(exit.m_jsValueSource.tag()), scratchTag);
+ JSValueRegs value(scratchTag, exit.m_jsValueSource.payloadGPR());
+ profile.emitReportValue(jit, value);
+ jit.popToRestore(scratchTag);
+ } else
+ profile.emitReportValue(jit, exit.m_jsValueSource.regs());
+#endif // USE(JSVALUE64)
}
}
@@ -378,13 +432,30 @@
const ValueRecovery& recovery = operands[index];
switch (recovery.technique()) {
+ case UnboxedInt32InGPR:
+ case UnboxedCellInGPR:
+#if USE(JSVALUE64)
case InGPR:
- case UnboxedInt32InGPR:
case UnboxedInt52InGPR:
case UnboxedStrictInt52InGPR:
- case UnboxedCellInGPR:
jit.store64(recovery.gpr(), scratch + index);
break;
+#else
+ case UnboxedBooleanInGPR:
+ jit.store32(
+ recovery.gpr(),
+ &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload);
+ break;
+
+ case InPair:
+ jit.store32(
+ recovery.tagGPR(),
+ &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.tag);
+ jit.store32(
+ recovery.payloadGPR(),
+ &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload);
+ break;
+#endif
default:
break;
@@ -425,11 +496,27 @@
case BooleanDisplacedInJSStack:
case Int32DisplacedInJSStack:
case DoubleDisplacedInJSStack:
+#if USE(JSVALUE64)
case Int52DisplacedInJSStack:
case StrictInt52DisplacedInJSStack:
jit.load64(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0);
jit.store64(GPRInfo::regT0, scratch + index);
break;
+#else
+ jit.load32(
+ AssemblyHelpers::tagFor(recovery.virtualRegister()),
+ GPRInfo::regT0);
+ jit.load32(
+ AssemblyHelpers::payloadFor(recovery.virtualRegister()),
+ GPRInfo::regT1);
+ jit.store32(
+ GPRInfo::regT0,
+ &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.tag);
+ jit.store32(
+ GPRInfo::regT1,
+ &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload);
+ break;
+#endif
default:
break;
@@ -466,24 +553,80 @@
int operand = reg.offset();
switch (recovery.technique()) {
+ case DisplacedInJSStack:
+ case InFPR:
+#if USE(JSVALUE64)
case InGPR:
case UnboxedCellInGPR:
- case DisplacedInJSStack:
case CellDisplacedInJSStack:
case BooleanDisplacedInJSStack:
- case InFPR:
jit.load64(scratch + index, GPRInfo::regT0);
jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
break;
+#else // not USE(JSVALUE64)
+ case InPair:
+ jit.load32(
+ &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.tag,
+ GPRInfo::regT0);
+ jit.load32(
+ &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload,
+ GPRInfo::regT1);
+ jit.store32(
+ GPRInfo::regT0,
+ AssemblyHelpers::tagFor(operand));
+ jit.store32(
+ GPRInfo::regT1,
+ AssemblyHelpers::payloadFor(operand));
+ break;
+ case UnboxedCellInGPR:
+ case CellDisplacedInJSStack:
+ jit.load32(
+ &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload,
+ GPRInfo::regT0);
+ jit.store32(
+ AssemblyHelpers::TrustedImm32(JSValue::CellTag),
+ AssemblyHelpers::tagFor(operand));
+ jit.store32(
+ GPRInfo::regT0,
+ AssemblyHelpers::payloadFor(operand));
+ break;
+
+ case UnboxedBooleanInGPR:
+ case BooleanDisplacedInJSStack:
+ jit.load32(
+ &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload,
+ GPRInfo::regT0);
+ jit.store32(
+ AssemblyHelpers::TrustedImm32(JSValue::BooleanTag),
+ AssemblyHelpers::tagFor(operand));
+ jit.store32(
+ GPRInfo::regT0,
+ AssemblyHelpers::payloadFor(operand));
+ break;
+#endif // USE(JSVALUE64)
+
case UnboxedInt32InGPR:
case Int32DisplacedInJSStack:
+#if USE(JSVALUE64)
jit.load64(scratch + index, GPRInfo::regT0);
jit.zeroExtend32ToPtr(GPRInfo::regT0, GPRInfo::regT0);
jit.or64(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
+#else
+ jit.load32(
+ &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload,
+ GPRInfo::regT0);
+ jit.store32(
+ AssemblyHelpers::TrustedImm32(JSValue::Int32Tag),
+ AssemblyHelpers::tagFor(operand));
+ jit.store32(
+ GPRInfo::regT0,
+ AssemblyHelpers::payloadFor(operand));
+#endif
break;
+#if USE(JSVALUE64)
case UnboxedInt52InGPR:
case Int52DisplacedInJSStack:
jit.load64(scratch + index, GPRInfo::regT0);
@@ -499,6 +642,7 @@
jit.boxInt52(GPRInfo::regT0, GPRInfo::regT0, GPRInfo::regT1, FPRInfo::fpRegT0);
jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
break;
+#endif
case UnboxedDoubleInFPR:
case DoubleDisplacedInJSStack:
@@ -505,14 +649,27 @@
jit.move(AssemblyHelpers::TrustedImmPtr(scratch + index), GPRInfo::regT0);
jit.loadDouble(MacroAssembler::Address(GPRInfo::regT0), FPRInfo::fpRegT0);
jit.purifyNaN(FPRInfo::fpRegT0);
+#if USE(JSVALUE64)
jit.boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0);
jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
+#else
+ jit.storeDouble(FPRInfo::fpRegT0, AssemblyHelpers::addressFor(operand));
+#endif
break;
case Constant:
+#if USE(JSVALUE64)
jit.store64(
AssemblyHelpers::TrustedImm64(JSValue::encode(recovery.constant())),
AssemblyHelpers::addressFor(operand));
+#else
+ jit.store32(
+ AssemblyHelpers::TrustedImm32(recovery.constant().tag()),
+ AssemblyHelpers::tagFor(operand));
+ jit.store32(
+ AssemblyHelpers::TrustedImm32(recovery.constant().payload()),
+ AssemblyHelpers::payloadFor(operand));
+#endif
break;
case DirectArgumentsThatWereNotCreated:
@@ -579,7 +736,6 @@
// And finish.
adjustAndJumpToTarget(vm, jit, exit);
}
-#endif // USE(JSVALUE64)
void JIT_OPERATION OSRExit::debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw, void* scratch)
{
Deleted: trunk/Source/_javascript_Core/dfg/DFGOSRExit32_64.cpp (220317 => 220318)
--- trunk/Source/_javascript_Core/dfg/DFGOSRExit32_64.cpp 2017-08-05 11:14:34 UTC (rev 220317)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExit32_64.cpp 2017-08-05 14:10:07 UTC (rev 220318)
@@ -1,411 +0,0 @@
-/*
- * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "DFGOSRExit.h"
-
-#if ENABLE(DFG_JIT) && USE(JSVALUE32_64)
-
-#include "DFGOSRExitCompilerCommon.h"
-#include "DFGOperations.h"
-#include "DFGSpeculativeJIT.h"
-#include "JSCInlines.h"
-#include <wtf/DataLog.h>
-
-namespace JSC { namespace DFG {
-
-void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const Operands<ValueRecovery>& operands, SpeculationRecovery* recovery)
-{
- // Pro-forma stuff.
- if (Options::printEachOSRExit()) {
- SpeculationFailureDebugInfo* debugInfo = new SpeculationFailureDebugInfo;
- debugInfo->codeBlock = jit.codeBlock();
- debugInfo->kind = exit.m_kind;
- debugInfo->bytecodeOffset = exit.m_codeOrigin.bytecodeIndex;
-
- jit.debugCall(vm, debugOperationPrintSpeculationFailure, debugInfo);
- }
-
- // Perform speculation recovery. This only comes into play when an operation
- // starts mutating state before verifying the speculation it has already made.
-
- if (recovery) {
- switch (recovery->type()) {
- case SpeculativeAdd:
- jit.sub32(recovery->src(), recovery->dest());
- break;
-
- case SpeculativeAddImmediate:
- jit.sub32(AssemblyHelpers::Imm32(recovery->immediate()), recovery->dest());
- break;
-
- case BooleanSpeculationCheck:
- break;
-
- default:
- break;
- }
- }
-
- // Refine some value profile, if appropriate.
-
- if (!!exit.m_jsValueSource) {
- if (exit.m_kind == BadCache || exit.m_kind == BadIndexingType) {
- // If the instruction that this originated from has an array profile, then
- // refine it. If it doesn't, then do nothing. The latter could happen for
- // hoisted checks, or checks emitted for operations that didn't have array
- // profiling - either ops that aren't array accesses at all, or weren't
- // known to be array acceses in the bytecode. The latter case is a FIXME
- // while the former case is an outcome of a CheckStructure not knowing why
- // it was emitted (could be either due to an inline cache of a property
- // property access, or due to an array profile).
-
- // Note: We are free to assume that the jsValueSource is already known to
- // be a cell since both BadCache and BadIndexingType exits occur after
- // the cell check would have already happened.
-
- CodeOrigin codeOrigin = exit.m_codeOriginForExitProfile;
- if (ArrayProfile* arrayProfile = jit.baselineCodeBlockFor(codeOrigin)->getArrayProfile(codeOrigin.bytecodeIndex)) {
- GPRReg usedRegister1;
- GPRReg usedRegister2;
- if (exit.m_jsValueSource.isAddress()) {
- usedRegister1 = exit.m_jsValueSource.base();
- usedRegister2 = InvalidGPRReg;
- } else {
- usedRegister1 = exit.m_jsValueSource.payloadGPR();
- if (exit.m_jsValueSource.hasKnownTag())
- usedRegister2 = InvalidGPRReg;
- else
- usedRegister2 = exit.m_jsValueSource.tagGPR();
- }
-
- GPRReg scratch1;
- GPRReg scratch2;
- scratch1 = AssemblyHelpers::selectScratchGPR(usedRegister1, usedRegister2);
- scratch2 = AssemblyHelpers::selectScratchGPR(usedRegister1, usedRegister2, scratch1);
-
- jit.push(scratch1);
- jit.push(scratch2);
-
- GPRReg value;
- if (exit.m_jsValueSource.isAddress()) {
- value = scratch1;
- jit.loadPtr(AssemblyHelpers::Address(exit.m_jsValueSource.asAddress()), value);
- } else
- value = exit.m_jsValueSource.payloadGPR();
-
- jit.loadPtr(AssemblyHelpers::Address(value, JSCell::structureIDOffset()), scratch1);
- jit.storePtr(scratch1, arrayProfile->addressOfLastSeenStructureID());
- jit.load8(AssemblyHelpers::Address(scratch1, Structure::indexingTypeIncludingHistoryOffset()), scratch1);
- jit.move(AssemblyHelpers::TrustedImm32(1), scratch2);
- jit.lshift32(scratch1, scratch2);
- jit.or32(scratch2, AssemblyHelpers::AbsoluteAddress(arrayProfile->addressOfArrayModes()));
-
- jit.pop(scratch2);
- jit.pop(scratch1);
- }
- }
-
- if (MethodOfGettingAValueProfile profile = "" {
- if (exit.m_jsValueSource.isAddress()) {
- // Save a register so we can use it.
- GPRReg scratchPayload = AssemblyHelpers::selectScratchGPR(exit.m_jsValueSource.base());
- GPRReg scratchTag = AssemblyHelpers::selectScratchGPR(exit.m_jsValueSource.base(), scratchPayload);
- jit.pushToSave(scratchPayload);
- jit.pushToSave(scratchTag);
-
- JSValueRegs scratch(scratchTag, scratchPayload);
-
- jit.loadValue(exit.m_jsValueSource.asAddress(), scratch);
- profile.emitReportValue(jit, scratch);
-
- jit.popToRestore(scratchTag);
- jit.popToRestore(scratchPayload);
- } else if (exit.m_jsValueSource.hasKnownTag()) {
- GPRReg scratchTag = AssemblyHelpers::selectScratchGPR(exit.m_jsValueSource.payloadGPR());
- jit.pushToSave(scratchTag);
- jit.move(AssemblyHelpers::TrustedImm32(exit.m_jsValueSource.tag()), scratchTag);
- JSValueRegs value(scratchTag, exit.m_jsValueSource.payloadGPR());
- profile.emitReportValue(jit, value);
- jit.popToRestore(scratchTag);
- } else
- profile.emitReportValue(jit, exit.m_jsValueSource.regs());
- }
- }
-
- // Do a simplified OSR exit. See DFGOSRExitCompiler64.cpp's comment regarding how and wny we
- // do this simple approach.
-
- // Save all state from GPRs into the scratch buffer.
-
- ScratchBuffer* scratchBuffer = vm.scratchBufferForSize(sizeof(EncodedJSValue) * operands.size());
- EncodedJSValue* scratch = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
-
- for (size_t index = 0; index < operands.size(); ++index) {
- const ValueRecovery& recovery = operands[index];
-
- switch (recovery.technique()) {
- case UnboxedInt32InGPR:
- case UnboxedBooleanInGPR:
- case UnboxedCellInGPR:
- jit.store32(
- recovery.gpr(),
- &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload);
- break;
-
- case InPair:
- jit.store32(
- recovery.tagGPR(),
- &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.tag);
- jit.store32(
- recovery.payloadGPR(),
- &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload);
- break;
-
- default:
- break;
- }
- }
-
- // Now all GPRs are free to reuse.
-
- // Save all state from FPRs into the scratch buffer.
-
- for (size_t index = 0; index < operands.size(); ++index) {
- const ValueRecovery& recovery = operands[index];
-
- switch (recovery.technique()) {
- case UnboxedDoubleInFPR:
- case InFPR:
- jit.move(AssemblyHelpers::TrustedImmPtr(scratch + index), GPRInfo::regT0);
- jit.storeDouble(recovery.fpr(), MacroAssembler::Address(GPRInfo::regT0));
- break;
-
- default:
- break;
- }
- }
-
- // Now all FPRs are free to reuse.
-
- // Save all state from the stack into the scratch buffer. For simplicity we
- // do this even for state that's already in the right place on the stack.
- // It makes things simpler later.
-
- for (size_t index = 0; index < operands.size(); ++index) {
- const ValueRecovery& recovery = operands[index];
-
- switch (recovery.technique()) {
- case DisplacedInJSStack:
- case Int32DisplacedInJSStack:
- case DoubleDisplacedInJSStack:
- case CellDisplacedInJSStack:
- case BooleanDisplacedInJSStack:
- jit.load32(
- AssemblyHelpers::tagFor(recovery.virtualRegister()),
- GPRInfo::regT0);
- jit.load32(
- AssemblyHelpers::payloadFor(recovery.virtualRegister()),
- GPRInfo::regT1);
- jit.store32(
- GPRInfo::regT0,
- &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.tag);
- jit.store32(
- GPRInfo::regT1,
- &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload);
- break;
-
- default:
- break;
- }
- }
-
- // Need to ensure that the stack pointer accounts for the worst-case stack usage at exit. This
- // could toast some stack that the DFG used. We need to do it before storing to stack offsets
- // used by baseline.
- jit.addPtr(
- CCallHelpers::TrustedImm32(
- -jit.codeBlock()->jitCode()->dfgCommon()->requiredRegisterCountForExit * sizeof(Register)),
- CCallHelpers::framePointerRegister, CCallHelpers::stackPointerRegister);
-
- // Restore the DFG callee saves and then save the ones the baseline JIT uses.
- jit.emitRestoreCalleeSaves();
- jit.emitSaveCalleeSavesFor(jit.baselineCodeBlock());
-
- if (exit.isExceptionHandler())
- jit.copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(vm);
-
- // Do all data format conversions and store the results into the stack.
-
- for (size_t index = 0; index < operands.size(); ++index) {
- const ValueRecovery& recovery = operands[index];
- VirtualRegister reg = operands.virtualRegisterForIndex(index);
-
- if (reg.isLocal() && reg.toLocal() < static_cast<int>(jit.baselineCodeBlock()->calleeSaveSpaceAsVirtualRegisters()))
- continue;
-
- int operand = reg.offset();
-
- switch (recovery.technique()) {
- case InPair:
- case DisplacedInJSStack:
- case InFPR:
- jit.load32(
- &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.tag,
- GPRInfo::regT0);
- jit.load32(
- &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload,
- GPRInfo::regT1);
- jit.store32(
- GPRInfo::regT0,
- AssemblyHelpers::tagFor(operand));
- jit.store32(
- GPRInfo::regT1,
- AssemblyHelpers::payloadFor(operand));
- break;
-
- case UnboxedDoubleInFPR:
- case DoubleDisplacedInJSStack:
- jit.move(AssemblyHelpers::TrustedImmPtr(scratch + index), GPRInfo::regT0);
- jit.loadDouble(MacroAssembler::Address(GPRInfo::regT0), FPRInfo::fpRegT0);
- jit.purifyNaN(FPRInfo::fpRegT0);
- jit.storeDouble(FPRInfo::fpRegT0, AssemblyHelpers::addressFor(operand));
- break;
-
- case UnboxedInt32InGPR:
- case Int32DisplacedInJSStack:
- jit.load32(
- &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload,
- GPRInfo::regT0);
- jit.store32(
- AssemblyHelpers::TrustedImm32(JSValue::Int32Tag),
- AssemblyHelpers::tagFor(operand));
- jit.store32(
- GPRInfo::regT0,
- AssemblyHelpers::payloadFor(operand));
- break;
-
- case UnboxedCellInGPR:
- case CellDisplacedInJSStack:
- jit.load32(
- &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload,
- GPRInfo::regT0);
- jit.store32(
- AssemblyHelpers::TrustedImm32(JSValue::CellTag),
- AssemblyHelpers::tagFor(operand));
- jit.store32(
- GPRInfo::regT0,
- AssemblyHelpers::payloadFor(operand));
- break;
-
- case UnboxedBooleanInGPR:
- case BooleanDisplacedInJSStack:
- jit.load32(
- &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.payload,
- GPRInfo::regT0);
- jit.store32(
- AssemblyHelpers::TrustedImm32(JSValue::BooleanTag),
- AssemblyHelpers::tagFor(operand));
- jit.store32(
- GPRInfo::regT0,
- AssemblyHelpers::payloadFor(operand));
- break;
-
- case Constant:
- jit.store32(
- AssemblyHelpers::TrustedImm32(recovery.constant().tag()),
- AssemblyHelpers::tagFor(operand));
- jit.store32(
- AssemblyHelpers::TrustedImm32(recovery.constant().payload()),
- AssemblyHelpers::payloadFor(operand));
- break;
-
- case DirectArgumentsThatWereNotCreated:
- case ClonedArgumentsThatWereNotCreated:
- // Don't do this, yet.
- break;
-
- default:
- break;
- }
- }
-
- // Now that things on the stack are recovered, do the arguments recovery. We assume that arguments
- // recoveries don't recursively refer to each other. But, we don't try to assume that they only
- // refer to certain ranges of locals. Hence why we need to do this here, once the stack is sensible.
- // Note that we also roughly assume that the arguments might still be materialized outside of its
- // inline call frame scope - but for now the DFG wouldn't do that.
-
- emitRestoreArguments(jit, operands);
-
- // Adjust the old JIT's execute counter. Since we are exiting OSR, we know
- // that all new calls into this code will go to the new JIT, so the execute
- // counter only affects call frames that performed OSR exit and call frames
- // that were still executing the old JIT at the time of another call frame's
- // OSR exit. We want to ensure that the following is true:
- //
- // (a) Code the performs an OSR exit gets a chance to reenter optimized
- // code eventually, since optimized code is faster. But we don't
- // want to do such reentery too aggressively (see (c) below).
- //
- // (b) If there is code on the call stack that is still running the old
- // JIT's code and has never OSR'd, then it should get a chance to
- // perform OSR entry despite the fact that we've exited.
- //
- // (c) Code the performs an OSR exit should not immediately retry OSR
- // entry, since both forms of OSR are expensive. OSR entry is
- // particularly expensive.
- //
- // (d) Frequent OSR failures, even those that do not result in the code
- // running in a hot loop, result in recompilation getting triggered.
- //
- // To ensure (c), we'd like to set the execute counter to
- // counterValueForOptimizeAfterWarmUp(). This seems like it would endanger
- // (a) and (b), since then every OSR exit would delay the opportunity for
- // every call frame to perform OSR entry. Essentially, if OSR exit happens
- // frequently and the function has few loops, then the counter will never
- // become non-negative and OSR entry will never be triggered. OSR entry
- // will only happen if a loop gets hot in the old JIT, which does a pretty
- // good job of ensuring (a) and (b). But that doesn't take care of (d),
- // since each speculation failure would reset the execute counter.
- // So we check here if the number of speculation failures is significantly
- // larger than the number of successes (we want 90% success rate), and if
- // there have been a large enough number of failures. If so, we set the
- // counter to 0; otherwise we set the counter to
- // counterValueForOptimizeAfterWarmUp().
-
- handleExitCounts(jit, exit);
-
- // Reify inlined call frames.
-
- reifyInlinedCallFrames(jit, exit);
-
- // And finish.
- adjustAndJumpToTarget(vm, jit, exit);
-}
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT) && USE(JSVALUE32_64)
Modified: trunk/Source/_javascript_Core/jit/GPRInfo.h (220317 => 220318)
--- trunk/Source/_javascript_Core/jit/GPRInfo.h 2017-08-05 11:14:34 UTC (rev 220317)
+++ trunk/Source/_javascript_Core/jit/GPRInfo.h 2017-08-05 14:10:07 UTC (rev 220318)
@@ -139,7 +139,9 @@
ASSERT(!isAddress());
return m_base;
}
-
+
+ GPRReg payloadGPR() const { return gpr(); }
+
JSValueRegs regs() const
{
return JSValueRegs(gpr());