Move DFG::OSRExitCompiler methods into DFG::OSRExit [step 3].
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 5 Aug 2017 14:10:07 +0000 (14:10 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 5 Aug 2017 14:10:07 +0000 (14:10 +0000)
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:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGOSRExit.cpp:
(JSC::DFG::OSRExit::compileExit):
* dfg/DFGOSRExit32_64.cpp: Removed.
* jit/GPRInfo.h:
(JSC::JSValueSource::payloadGPR const):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@220318 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/dfg/DFGOSRExit.cpp
Source/JavaScriptCore/dfg/DFGOSRExit32_64.cpp [deleted file]
Source/JavaScriptCore/jit/GPRInfo.h

index 508d92c..3b3b513 100644 (file)
@@ -376,7 +376,6 @@ set(JavaScriptCore_SOURCES
     dfg/DFGOSREntry.cpp
     dfg/DFGOSREntrypointCreationPhase.cpp
     dfg/DFGOSRExit.cpp
-    dfg/DFGOSRExit32_64.cpp
     dfg/DFGOSRExitBase.cpp
     dfg/DFGOSRExitCompilerCommon.cpp
     dfg/DFGOSRExitFuzz.cpp
index c6b0edd..d0cdd39 100644 (file)
@@ -1,3 +1,22 @@
+2017-08-05  Mark Lam  <mark.lam@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:
+        * JavaScriptCore.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  <youenn@apple.com>
 
         [Cache API] Add Cache and CacheStorage IDL definitions
index c47398a..9b59b23 100644 (file)
                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 */; };
                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>"; };
                                0FD8A31E17D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.h */,
                                0FC0978E146A6F6300CF2442 /* DFGOSRExit.cpp */,
                                0FC097681468A6EF00CF2442 /* DFGOSRExit.h */,
-                               0FC09775146943AD00CF2442 /* DFGOSRExit32_64.cpp */,
                                0F235BE717178E7300690C7F /* DFGOSRExitBase.cpp */,
                                0F235BE817178E7300690C7F /* DFGOSRExitBase.h */,
                                65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */,
                                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 */,
index 34dc1bd..d6e2a43 100644 (file)
@@ -223,8 +223,6 @@ void JIT_OPERATION OSRExit::compileOSRExit(ExecState* exec)
     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 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
         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 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
 
             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 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
                     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 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
         }
 
         if (MethodOfGettingAValueProfile profile = exit.m_valueProfile) {
+#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 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
                 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 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
         const ValueRecovery& recovery = operands[index];
 
         switch (recovery.technique()) {
-        case InGPR:
         case UnboxedInt32InGPR:
+        case UnboxedCellInGPR:
+#if USE(JSVALUE64)
+        case InGPR:
         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 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
         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 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
         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,20 +642,34 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
             jit.boxInt52(GPRInfo::regT0, GPRInfo::regT0, GPRInfo::regT1, FPRInfo::fpRegT0);
             jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
             break;
+#endif
 
         case UnboxedDoubleInFPR:
         case DoubleDisplacedInJSStack:
             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 @@ void OSRExit::compileExit(CCallHelpers& jit, VM& vm, const OSRExit& exit, const
     // And finish.
     adjustAndJumpToTarget(vm, jit, exit);
 }
-#endif // USE(JSVALUE64)
 
 void JIT_OPERATION OSRExit::debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw, void* scratch)
 {
diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit32_64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExit32_64.cpp
deleted file mode 100644 (file)
index 3d4d30b..0000000
+++ /dev/null
@@ -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 = exit.m_valueProfile) {
-            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)
index ffc757d..b596124 100644 (file)
@@ -139,7 +139,9 @@ public:
         ASSERT(!isAddress());
         return m_base;
     }
-    
+
+    GPRReg payloadGPR() const { return gpr(); }
+
     JSValueRegs regs() const
     {
         return JSValueRegs(gpr());