12bde8e466a4451c7319e3a072d118917957d6554Steve Block/* 22bde8e466a4451c7319e3a072d118917957d6554Steve Block * Copyright (C) 2011 Apple Inc. All rights reserved. 32bde8e466a4451c7319e3a072d118917957d6554Steve Block * 42bde8e466a4451c7319e3a072d118917957d6554Steve Block * Redistribution and use in source and binary forms, with or without 52bde8e466a4451c7319e3a072d118917957d6554Steve Block * modification, are permitted provided that the following conditions 62bde8e466a4451c7319e3a072d118917957d6554Steve Block * are met: 72bde8e466a4451c7319e3a072d118917957d6554Steve Block * 1. Redistributions of source code must retain the above copyright 82bde8e466a4451c7319e3a072d118917957d6554Steve Block * notice, this list of conditions and the following disclaimer. 92bde8e466a4451c7319e3a072d118917957d6554Steve Block * 2. Redistributions in binary form must reproduce the above copyright 102bde8e466a4451c7319e3a072d118917957d6554Steve Block * notice, this list of conditions and the following disclaimer in the 112bde8e466a4451c7319e3a072d118917957d6554Steve Block * documentation and/or other materials provided with the distribution. 122bde8e466a4451c7319e3a072d118917957d6554Steve Block * 132bde8e466a4451c7319e3a072d118917957d6554Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 142bde8e466a4451c7319e3a072d118917957d6554Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 152bde8e466a4451c7319e3a072d118917957d6554Steve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 162bde8e466a4451c7319e3a072d118917957d6554Steve Block * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 172bde8e466a4451c7319e3a072d118917957d6554Steve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 182bde8e466a4451c7319e3a072d118917957d6554Steve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 192bde8e466a4451c7319e3a072d118917957d6554Steve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 202bde8e466a4451c7319e3a072d118917957d6554Steve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 212bde8e466a4451c7319e3a072d118917957d6554Steve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 222bde8e466a4451c7319e3a072d118917957d6554Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 232bde8e466a4451c7319e3a072d118917957d6554Steve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 242bde8e466a4451c7319e3a072d118917957d6554Steve Block */ 252bde8e466a4451c7319e3a072d118917957d6554Steve Block 262bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "config.h" 272bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "DFGJITCompiler.h" 282bde8e466a4451c7319e3a072d118917957d6554Steve Block 292bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(DFG_JIT) 302bde8e466a4451c7319e3a072d118917957d6554Steve Block 312bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "CodeBlock.h" 322bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "DFGJITCodeGenerator.h" 332bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "DFGNonSpeculativeJIT.h" 342bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "DFGOperations.h" 352bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "DFGRegisterBank.h" 362bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "DFGSpeculativeJIT.h" 372bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "JSGlobalData.h" 382bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "LinkBuffer.h" 392bde8e466a4451c7319e3a072d118917957d6554Steve Block 402bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace JSC { namespace DFG { 412bde8e466a4451c7319e3a072d118917957d6554Steve Block 422bde8e466a4451c7319e3a072d118917957d6554Steve Block// This method used to fill a numeric value to a FPR when linking speculative -> non-speculative. 432bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::fillNumericToDouble(NodeIndex nodeIndex, FPRReg fpr, GPRReg temporary) 442bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 452bde8e466a4451c7319e3a072d118917957d6554Steve Block Node& node = graph()[nodeIndex]; 462bde8e466a4451c7319e3a072d118917957d6554Steve Block MacroAssembler::RegisterID tempReg = gprToRegisterID(temporary); 472bde8e466a4451c7319e3a072d118917957d6554Steve Block 482bde8e466a4451c7319e3a072d118917957d6554Steve Block if (node.isConstant()) { 492bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(node.op == DoubleConstant); 502bde8e466a4451c7319e3a072d118917957d6554Steve Block move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), tempReg); 512bde8e466a4451c7319e3a072d118917957d6554Steve Block movePtrToDouble(tempReg, fprToRegisterID(fpr)); 522bde8e466a4451c7319e3a072d118917957d6554Steve Block } else { 532bde8e466a4451c7319e3a072d118917957d6554Steve Block loadPtr(addressFor(node.virtualRegister), tempReg); 542bde8e466a4451c7319e3a072d118917957d6554Steve Block Jump isInteger = branchPtr(MacroAssembler::AboveOrEqual, tempReg, tagTypeNumberRegister); 552bde8e466a4451c7319e3a072d118917957d6554Steve Block jitAssertIsJSDouble(gpr0); 562bde8e466a4451c7319e3a072d118917957d6554Steve Block addPtr(tagTypeNumberRegister, tempReg); 572bde8e466a4451c7319e3a072d118917957d6554Steve Block movePtrToDouble(tempReg, fprToRegisterID(fpr)); 582bde8e466a4451c7319e3a072d118917957d6554Steve Block Jump hasUnboxedDouble = jump(); 592bde8e466a4451c7319e3a072d118917957d6554Steve Block isInteger.link(this); 602bde8e466a4451c7319e3a072d118917957d6554Steve Block convertInt32ToDouble(tempReg, fprToRegisterID(fpr)); 612bde8e466a4451c7319e3a072d118917957d6554Steve Block hasUnboxedDouble.link(this); 622bde8e466a4451c7319e3a072d118917957d6554Steve Block } 632bde8e466a4451c7319e3a072d118917957d6554Steve Block} 642bde8e466a4451c7319e3a072d118917957d6554Steve Block 652bde8e466a4451c7319e3a072d118917957d6554Steve Block// This method used to fill an integer value to a GPR when linking speculative -> non-speculative. 662bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::fillInt32ToInteger(NodeIndex nodeIndex, GPRReg gpr) 672bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 682bde8e466a4451c7319e3a072d118917957d6554Steve Block Node& node = graph()[nodeIndex]; 692bde8e466a4451c7319e3a072d118917957d6554Steve Block 702bde8e466a4451c7319e3a072d118917957d6554Steve Block if (node.isConstant()) { 712bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(node.op == Int32Constant); 722bde8e466a4451c7319e3a072d118917957d6554Steve Block move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gprToRegisterID(gpr)); 732bde8e466a4451c7319e3a072d118917957d6554Steve Block } else { 742bde8e466a4451c7319e3a072d118917957d6554Steve Block#if DFG_JIT_ASSERT 752bde8e466a4451c7319e3a072d118917957d6554Steve Block // Redundant load, just so we can check the tag! 762bde8e466a4451c7319e3a072d118917957d6554Steve Block loadPtr(addressFor(node.virtualRegister), gprToRegisterID(gpr)); 772bde8e466a4451c7319e3a072d118917957d6554Steve Block jitAssertIsJSInt32(gpr); 782bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 792bde8e466a4451c7319e3a072d118917957d6554Steve Block load32(addressFor(node.virtualRegister), gprToRegisterID(gpr)); 802bde8e466a4451c7319e3a072d118917957d6554Steve Block } 812bde8e466a4451c7319e3a072d118917957d6554Steve Block} 822bde8e466a4451c7319e3a072d118917957d6554Steve Block 832bde8e466a4451c7319e3a072d118917957d6554Steve Block// This method used to fill a JSValue to a GPR when linking speculative -> non-speculative. 842bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::fillToJS(NodeIndex nodeIndex, GPRReg gpr) 852bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 862bde8e466a4451c7319e3a072d118917957d6554Steve Block Node& node = graph()[nodeIndex]; 872bde8e466a4451c7319e3a072d118917957d6554Steve Block 882bde8e466a4451c7319e3a072d118917957d6554Steve Block if (node.isConstant()) { 892bde8e466a4451c7319e3a072d118917957d6554Steve Block if (isInt32Constant(nodeIndex)) { 902bde8e466a4451c7319e3a072d118917957d6554Steve Block JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex)); 912bde8e466a4451c7319e3a072d118917957d6554Steve Block move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gprToRegisterID(gpr)); 922bde8e466a4451c7319e3a072d118917957d6554Steve Block } else if (isDoubleConstant(nodeIndex)) { 932bde8e466a4451c7319e3a072d118917957d6554Steve Block JSValue jsValue(JSValue::EncodeAsDouble, valueOfDoubleConstant(nodeIndex)); 942bde8e466a4451c7319e3a072d118917957d6554Steve Block move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gprToRegisterID(gpr)); 952bde8e466a4451c7319e3a072d118917957d6554Steve Block } else { 962bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(isJSConstant(nodeIndex)); 972bde8e466a4451c7319e3a072d118917957d6554Steve Block JSValue jsValue = valueOfJSConstant(nodeIndex); 982bde8e466a4451c7319e3a072d118917957d6554Steve Block move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gprToRegisterID(gpr)); 992bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1002bde8e466a4451c7319e3a072d118917957d6554Steve Block return; 1012bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1022bde8e466a4451c7319e3a072d118917957d6554Steve Block 1032bde8e466a4451c7319e3a072d118917957d6554Steve Block loadPtr(addressFor(node.virtualRegister), gprToRegisterID(gpr)); 1042bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1052bde8e466a4451c7319e3a072d118917957d6554Steve Block 1062bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::jumpFromSpeculativeToNonSpeculative(const SpeculationCheck& check, const EntryLocation& entry, SpeculationRecovery* recovery) 1072bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1082bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(check.m_nodeIndex == entry.m_nodeIndex); 1092bde8e466a4451c7319e3a072d118917957d6554Steve Block 1102bde8e466a4451c7319e3a072d118917957d6554Steve Block // Link the jump from the Speculative path to here. 1112bde8e466a4451c7319e3a072d118917957d6554Steve Block check.m_check.link(this); 1122bde8e466a4451c7319e3a072d118917957d6554Steve Block 1132bde8e466a4451c7319e3a072d118917957d6554Steve Block // Does this speculation check require any additional recovery to be performed, 1142bde8e466a4451c7319e3a072d118917957d6554Steve Block // to restore any state that has been overwritten before we enter back in to the 1152bde8e466a4451c7319e3a072d118917957d6554Steve Block // non-speculative path. 1162bde8e466a4451c7319e3a072d118917957d6554Steve Block if (recovery) { 1172bde8e466a4451c7319e3a072d118917957d6554Steve Block // The only additional recovery we currently support is for integer add operation 1182bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(recovery->type() == SpeculativeAdd); 1192bde8e466a4451c7319e3a072d118917957d6554Steve Block // Revert the add. 1202bde8e466a4451c7319e3a072d118917957d6554Steve Block sub32(gprToRegisterID(recovery->src()), gprToRegisterID(recovery->dest())); 1212bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1222bde8e466a4451c7319e3a072d118917957d6554Steve Block 1232bde8e466a4451c7319e3a072d118917957d6554Steve Block // FIXME: - This is hideously inefficient! 1242bde8e466a4451c7319e3a072d118917957d6554Steve Block // Where a value is live in a register in the speculative path, and is required in a register 1252bde8e466a4451c7319e3a072d118917957d6554Steve Block // on the non-speculative path, we should not need to be spilling it and reloading (we may 1262bde8e466a4451c7319e3a072d118917957d6554Steve Block // need to spill anyway, if the value is marked as spilled on the non-speculative path). 1272bde8e466a4451c7319e3a072d118917957d6554Steve Block // This may also be spilling values that don't need spilling, e.g. are already spilled, 1282bde8e466a4451c7319e3a072d118917957d6554Steve Block // are constants, or are arguments. 1292bde8e466a4451c7319e3a072d118917957d6554Steve Block 1302bde8e466a4451c7319e3a072d118917957d6554Steve Block // Spill all GPRs in use by the speculative path. 1312bde8e466a4451c7319e3a072d118917957d6554Steve Block for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) { 1322bde8e466a4451c7319e3a072d118917957d6554Steve Block NodeIndex nodeIndex = check.m_gprInfo[gpr].nodeIndex; 1332bde8e466a4451c7319e3a072d118917957d6554Steve Block if (nodeIndex == NoNode) 1342bde8e466a4451c7319e3a072d118917957d6554Steve Block continue; 1352bde8e466a4451c7319e3a072d118917957d6554Steve Block 1362bde8e466a4451c7319e3a072d118917957d6554Steve Block DataFormat dataFormat = check.m_gprInfo[gpr].format; 1372bde8e466a4451c7319e3a072d118917957d6554Steve Block VirtualRegister virtualRegister = graph()[nodeIndex].virtualRegister; 1382bde8e466a4451c7319e3a072d118917957d6554Steve Block 1392bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(dataFormat == DataFormatInteger || DataFormatCell || dataFormat & DataFormatJS); 1402bde8e466a4451c7319e3a072d118917957d6554Steve Block if (dataFormat == DataFormatInteger) 1412bde8e466a4451c7319e3a072d118917957d6554Steve Block orPtr(tagTypeNumberRegister, gprToRegisterID(gpr)); 1422bde8e466a4451c7319e3a072d118917957d6554Steve Block storePtr(gprToRegisterID(gpr), addressFor(virtualRegister)); 1432bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1442bde8e466a4451c7319e3a072d118917957d6554Steve Block 1452bde8e466a4451c7319e3a072d118917957d6554Steve Block // Spill all FPRs in use by the speculative path. 1462bde8e466a4451c7319e3a072d118917957d6554Steve Block for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) { 1472bde8e466a4451c7319e3a072d118917957d6554Steve Block NodeIndex nodeIndex = check.m_fprInfo[fpr]; 1482bde8e466a4451c7319e3a072d118917957d6554Steve Block if (nodeIndex == NoNode) 1492bde8e466a4451c7319e3a072d118917957d6554Steve Block continue; 1502bde8e466a4451c7319e3a072d118917957d6554Steve Block 1512bde8e466a4451c7319e3a072d118917957d6554Steve Block VirtualRegister virtualRegister = graph()[nodeIndex].virtualRegister; 1522bde8e466a4451c7319e3a072d118917957d6554Steve Block 1532bde8e466a4451c7319e3a072d118917957d6554Steve Block moveDoubleToPtr(fprToRegisterID(fpr), regT0); 1542bde8e466a4451c7319e3a072d118917957d6554Steve Block subPtr(tagTypeNumberRegister, regT0); 1552bde8e466a4451c7319e3a072d118917957d6554Steve Block storePtr(regT0, addressFor(virtualRegister)); 1562bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1572bde8e466a4451c7319e3a072d118917957d6554Steve Block 1582bde8e466a4451c7319e3a072d118917957d6554Steve Block // Fill all FPRs in use by the non-speculative path. 1592bde8e466a4451c7319e3a072d118917957d6554Steve Block for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) { 1602bde8e466a4451c7319e3a072d118917957d6554Steve Block NodeIndex nodeIndex = entry.m_fprInfo[fpr]; 1612bde8e466a4451c7319e3a072d118917957d6554Steve Block if (nodeIndex == NoNode) 1622bde8e466a4451c7319e3a072d118917957d6554Steve Block continue; 1632bde8e466a4451c7319e3a072d118917957d6554Steve Block 1642bde8e466a4451c7319e3a072d118917957d6554Steve Block fillNumericToDouble(nodeIndex, fpr, gpr0); 1652bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1662bde8e466a4451c7319e3a072d118917957d6554Steve Block 1672bde8e466a4451c7319e3a072d118917957d6554Steve Block // Fill all GPRs in use by the non-speculative path. 1682bde8e466a4451c7319e3a072d118917957d6554Steve Block for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) { 1692bde8e466a4451c7319e3a072d118917957d6554Steve Block NodeIndex nodeIndex = entry.m_gprInfo[gpr].nodeIndex; 1702bde8e466a4451c7319e3a072d118917957d6554Steve Block if (nodeIndex == NoNode) 1712bde8e466a4451c7319e3a072d118917957d6554Steve Block continue; 1722bde8e466a4451c7319e3a072d118917957d6554Steve Block 1732bde8e466a4451c7319e3a072d118917957d6554Steve Block DataFormat dataFormat = entry.m_gprInfo[gpr].format; 1742bde8e466a4451c7319e3a072d118917957d6554Steve Block if (dataFormat == DataFormatInteger) 1752bde8e466a4451c7319e3a072d118917957d6554Steve Block fillInt32ToInteger(nodeIndex, gpr); 1762bde8e466a4451c7319e3a072d118917957d6554Steve Block else { 1772bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(dataFormat & DataFormatJS || dataFormat == DataFormatCell); // Treat cell as JSValue for now! 1782bde8e466a4451c7319e3a072d118917957d6554Steve Block fillToJS(nodeIndex, gpr); 1792bde8e466a4451c7319e3a072d118917957d6554Steve Block // FIXME: For subtypes of DataFormatJS, should jitAssert the subtype? 1802bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1812bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1822bde8e466a4451c7319e3a072d118917957d6554Steve Block 1832bde8e466a4451c7319e3a072d118917957d6554Steve Block // Jump into the non-speculative path. 1842bde8e466a4451c7319e3a072d118917957d6554Steve Block jump(entry.m_entry); 1852bde8e466a4451c7319e3a072d118917957d6554Steve Block} 1862bde8e466a4451c7319e3a072d118917957d6554Steve Block 1872bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::linkSpeculationChecks(SpeculativeJIT& speculative, NonSpeculativeJIT& nonSpeculative) 1882bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 1892bde8e466a4451c7319e3a072d118917957d6554Steve Block // Iterators to walk over the set of bail outs & corresponding entry points. 1902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch SpeculationCheckVector::Iterator checksIter = speculative.speculationChecks().begin(); 1912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch SpeculationCheckVector::Iterator checksEnd = speculative.speculationChecks().end(); 1922bde8e466a4451c7319e3a072d118917957d6554Steve Block NonSpeculativeJIT::EntryLocationVector::Iterator entriesIter = nonSpeculative.entryLocations().begin(); 1932bde8e466a4451c7319e3a072d118917957d6554Steve Block NonSpeculativeJIT::EntryLocationVector::Iterator entriesEnd = nonSpeculative.entryLocations().end(); 1942bde8e466a4451c7319e3a072d118917957d6554Steve Block 1952bde8e466a4451c7319e3a072d118917957d6554Steve Block // Iterate over the speculation checks. 1962bde8e466a4451c7319e3a072d118917957d6554Steve Block while (checksIter != checksEnd) { 1972bde8e466a4451c7319e3a072d118917957d6554Steve Block // For every bail out from the speculative path, we must have provided an entry point 1982bde8e466a4451c7319e3a072d118917957d6554Steve Block // into the non-speculative one. 1992bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(checksIter->m_nodeIndex == entriesIter->m_nodeIndex); 2002bde8e466a4451c7319e3a072d118917957d6554Steve Block 2012bde8e466a4451c7319e3a072d118917957d6554Steve Block // There may be multiple bail outs that map to the same entry point! 2022bde8e466a4451c7319e3a072d118917957d6554Steve Block do { 2032bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(checksIter != checksEnd); 2042bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(entriesIter != entriesEnd); 2052bde8e466a4451c7319e3a072d118917957d6554Steve Block 2062bde8e466a4451c7319e3a072d118917957d6554Steve Block // Plant code to link this speculation failure. 2072bde8e466a4451c7319e3a072d118917957d6554Steve Block const SpeculationCheck& check = *checksIter; 2082bde8e466a4451c7319e3a072d118917957d6554Steve Block const EntryLocation& entry = *entriesIter; 2092bde8e466a4451c7319e3a072d118917957d6554Steve Block jumpFromSpeculativeToNonSpeculative(check, entry, speculative.speculationRecovery(check.m_recoveryIndex)); 2102bde8e466a4451c7319e3a072d118917957d6554Steve Block ++checksIter; 2112bde8e466a4451c7319e3a072d118917957d6554Steve Block } while (checksIter != checksEnd && checksIter->m_nodeIndex == entriesIter->m_nodeIndex); 2122bde8e466a4451c7319e3a072d118917957d6554Steve Block ++entriesIter; 2132bde8e466a4451c7319e3a072d118917957d6554Steve Block } 2142bde8e466a4451c7319e3a072d118917957d6554Steve Block 2152bde8e466a4451c7319e3a072d118917957d6554Steve Block // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56289 2162bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(!(checksIter != checksEnd)); 2172bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT(!(entriesIter != entriesEnd)); 2182bde8e466a4451c7319e3a072d118917957d6554Steve Block} 2192bde8e466a4451c7319e3a072d118917957d6554Steve Block 2202bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck) 2212bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 2222bde8e466a4451c7319e3a072d118917957d6554Steve Block // === Stage 1 - Function header code generation === 2232bde8e466a4451c7319e3a072d118917957d6554Steve Block // 2242bde8e466a4451c7319e3a072d118917957d6554Steve Block // This code currently matches the old JIT. In the function header we need to 2252bde8e466a4451c7319e3a072d118917957d6554Steve Block // pop the return address (since we do not allow any recursion on the machine 2262bde8e466a4451c7319e3a072d118917957d6554Steve Block // stack), and perform a fast register file check. 2272bde8e466a4451c7319e3a072d118917957d6554Steve Block 2282bde8e466a4451c7319e3a072d118917957d6554Steve Block // This is the main entry point, without performing an arity check. 2292bde8e466a4451c7319e3a072d118917957d6554Steve Block // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56292 2302bde8e466a4451c7319e3a072d118917957d6554Steve Block // We'll need to convert the remaining cti_ style calls (specifically the register file 2312bde8e466a4451c7319e3a072d118917957d6554Steve Block // check) which will be dependent on stack layout. (We'd need to account for this in 2322bde8e466a4451c7319e3a072d118917957d6554Steve Block // both normal return code and when jumping to an exception handler). 2332bde8e466a4451c7319e3a072d118917957d6554Steve Block preserveReturnAddressAfterCall(regT2); 2342bde8e466a4451c7319e3a072d118917957d6554Steve Block emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC); 2352bde8e466a4451c7319e3a072d118917957d6554Steve Block // If we needed to perform an arity check we will already have moved the return address, 2362bde8e466a4451c7319e3a072d118917957d6554Steve Block // so enter after this. 2372bde8e466a4451c7319e3a072d118917957d6554Steve Block Label fromArityCheck(this); 2382bde8e466a4451c7319e3a072d118917957d6554Steve Block 2392bde8e466a4451c7319e3a072d118917957d6554Steve Block // Setup a pointer to the codeblock in the CallFrameHeader. 2402bde8e466a4451c7319e3a072d118917957d6554Steve Block emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock); 2412bde8e466a4451c7319e3a072d118917957d6554Steve Block 2422bde8e466a4451c7319e3a072d118917957d6554Steve Block // Plant a check that sufficient space is available in the RegisterFile. 2432bde8e466a4451c7319e3a072d118917957d6554Steve Block // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291 2442bde8e466a4451c7319e3a072d118917957d6554Steve Block addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, regT1); 2452bde8e466a4451c7319e3a072d118917957d6554Steve Block Jump registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1); 2462bde8e466a4451c7319e3a072d118917957d6554Steve Block // Return here after register file check. 2472bde8e466a4451c7319e3a072d118917957d6554Steve Block Label fromRegisterFileCheck = label(); 2482bde8e466a4451c7319e3a072d118917957d6554Steve Block 2492bde8e466a4451c7319e3a072d118917957d6554Steve Block 2502bde8e466a4451c7319e3a072d118917957d6554Steve Block // === Stage 2 - Function body code generation === 2512bde8e466a4451c7319e3a072d118917957d6554Steve Block // 2522bde8e466a4451c7319e3a072d118917957d6554Steve Block // We generate the speculative code path, followed by the non-speculative 2532bde8e466a4451c7319e3a072d118917957d6554Steve Block // code for the function. Next we need to link the two together, making 2542bde8e466a4451c7319e3a072d118917957d6554Steve Block // bail-outs from the speculative path jump to the corresponding point on 2552bde8e466a4451c7319e3a072d118917957d6554Steve Block // the non-speculative one (and generating any code necessary to juggle 2562bde8e466a4451c7319e3a072d118917957d6554Steve Block // register values around, rebox values, and ensure spilled, to match the 2572bde8e466a4451c7319e3a072d118917957d6554Steve Block // non-speculative path's requirements). 2582bde8e466a4451c7319e3a072d118917957d6554Steve Block 2592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if DFG_JIT_BREAK_ON_EVERY_FUNCTION 2602bde8e466a4451c7319e3a072d118917957d6554Steve Block // Handy debug tool! 2612bde8e466a4451c7319e3a072d118917957d6554Steve Block breakpoint(); 2622bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 2632bde8e466a4451c7319e3a072d118917957d6554Steve Block 2642bde8e466a4451c7319e3a072d118917957d6554Steve Block // First generate the speculative path. 2652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch Label speculativePathBegin = label(); 2662bde8e466a4451c7319e3a072d118917957d6554Steve Block SpeculativeJIT speculative(*this); 2672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch bool compiledSpeculative = speculative.compile(); 2682bde8e466a4451c7319e3a072d118917957d6554Steve Block 2692bde8e466a4451c7319e3a072d118917957d6554Steve Block // Next, generate the non-speculative path. We pass this a SpeculationCheckIndexIterator 2702bde8e466a4451c7319e3a072d118917957d6554Steve Block // to allow it to check which nodes in the graph may bail out, and may need to reenter the 2712bde8e466a4451c7319e3a072d118917957d6554Steve Block // non-speculative path. 2722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (compiledSpeculative) { 2732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch SpeculationCheckIndexIterator checkIterator(speculative.speculationChecks()); 2742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch NonSpeculativeJIT nonSpeculative(*this); 2752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch nonSpeculative.compile(checkIterator); 2762bde8e466a4451c7319e3a072d118917957d6554Steve Block 2772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // Link the bail-outs from the speculative path to the corresponding entry points into the non-speculative one. 2782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch linkSpeculationChecks(speculative, nonSpeculative); 2792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } else { 2802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // If compilation through the SpeculativeJIT failed, throw away the code we generated. 2812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch m_calls.clear(); 2822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch rewindToLabel(speculativePathBegin); 2832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 2842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch SpeculationCheckVector noChecks; 2852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch SpeculationCheckIndexIterator checkIterator(noChecks); 2862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch NonSpeculativeJIT nonSpeculative(*this); 2872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch nonSpeculative.compile(checkIterator); 2882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch } 2892bde8e466a4451c7319e3a072d118917957d6554Steve Block 2902bde8e466a4451c7319e3a072d118917957d6554Steve Block // === Stage 3 - Function footer code generation === 2912bde8e466a4451c7319e3a072d118917957d6554Steve Block // 2922bde8e466a4451c7319e3a072d118917957d6554Steve Block // Generate code to lookup and jump to exception handlers, to perform the slow 2932bde8e466a4451c7319e3a072d118917957d6554Steve Block // register file check (if the fast one in the function header fails), and 2942bde8e466a4451c7319e3a072d118917957d6554Steve Block // generate the entry point with arity check. 2952bde8e466a4451c7319e3a072d118917957d6554Steve Block 2962bde8e466a4451c7319e3a072d118917957d6554Steve Block // Iterate over the m_calls vector, checking for exception checks, 2972bde8e466a4451c7319e3a072d118917957d6554Steve Block // and linking them to here. 2982bde8e466a4451c7319e3a072d118917957d6554Steve Block unsigned exceptionCheckCount = 0; 2992bde8e466a4451c7319e3a072d118917957d6554Steve Block for (unsigned i = 0; i < m_calls.size(); ++i) { 3002bde8e466a4451c7319e3a072d118917957d6554Steve Block Jump& exceptionCheck = m_calls[i].m_exceptionCheck; 3012bde8e466a4451c7319e3a072d118917957d6554Steve Block if (exceptionCheck.isSet()) { 3022bde8e466a4451c7319e3a072d118917957d6554Steve Block exceptionCheck.link(this); 3032bde8e466a4451c7319e3a072d118917957d6554Steve Block ++exceptionCheckCount; 3042bde8e466a4451c7319e3a072d118917957d6554Steve Block } 3052bde8e466a4451c7319e3a072d118917957d6554Steve Block } 3062bde8e466a4451c7319e3a072d118917957d6554Steve Block // If any exception checks were linked, generate code to lookup a handler. 3072bde8e466a4451c7319e3a072d118917957d6554Steve Block if (exceptionCheckCount) { 3082bde8e466a4451c7319e3a072d118917957d6554Steve Block // lookupExceptionHandler is passed two arguments, exec (the CallFrame*), and 3092bde8e466a4451c7319e3a072d118917957d6554Steve Block // an identifier for the operation that threw the exception, which we can use 3102bde8e466a4451c7319e3a072d118917957d6554Steve Block // to look up handler information. The identifier we use is the return address 3112bde8e466a4451c7319e3a072d118917957d6554Steve Block // of the call out from JIT code that threw the exception; this is still 3122bde8e466a4451c7319e3a072d118917957d6554Steve Block // available on the stack, just below the stack pointer! 3132bde8e466a4451c7319e3a072d118917957d6554Steve Block move(callFrameRegister, argumentRegister0); 3142bde8e466a4451c7319e3a072d118917957d6554Steve Block peek(argumentRegister1, -1); 3152bde8e466a4451c7319e3a072d118917957d6554Steve Block m_calls.append(CallRecord(call(), lookupExceptionHandler)); 3162bde8e466a4451c7319e3a072d118917957d6554Steve Block // lookupExceptionHandler leaves the handler CallFrame* in the returnValueRegister, 3172bde8e466a4451c7319e3a072d118917957d6554Steve Block // and the address of the handler in returnValueRegister2. 3182bde8e466a4451c7319e3a072d118917957d6554Steve Block jump(returnValueRegister2); 3192bde8e466a4451c7319e3a072d118917957d6554Steve Block } 3202bde8e466a4451c7319e3a072d118917957d6554Steve Block 3212bde8e466a4451c7319e3a072d118917957d6554Steve Block // Generate the register file check; if the fast check in the function head fails, 3222bde8e466a4451c7319e3a072d118917957d6554Steve Block // we need to call out to a helper function to check whether more space is available. 3232bde8e466a4451c7319e3a072d118917957d6554Steve Block // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions). 3242bde8e466a4451c7319e3a072d118917957d6554Steve Block registerFileCheck.link(this); 3252bde8e466a4451c7319e3a072d118917957d6554Steve Block move(stackPointerRegister, argumentRegister0); 3262bde8e466a4451c7319e3a072d118917957d6554Steve Block poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); 3272bde8e466a4451c7319e3a072d118917957d6554Steve Block Call callRegisterFileCheck = call(); 3282bde8e466a4451c7319e3a072d118917957d6554Steve Block jump(fromRegisterFileCheck); 3292bde8e466a4451c7319e3a072d118917957d6554Steve Block 3302bde8e466a4451c7319e3a072d118917957d6554Steve Block // The fast entry point into a function does not check the correct number of arguments 3312bde8e466a4451c7319e3a072d118917957d6554Steve Block // have been passed to the call (we only use the fast entry point where we can statically 3322bde8e466a4451c7319e3a072d118917957d6554Steve Block // determine the correct number of arguments have been passed, or have already checked). 3332bde8e466a4451c7319e3a072d118917957d6554Steve Block // In cases where an arity check is necessary, we enter here. 3342bde8e466a4451c7319e3a072d118917957d6554Steve Block // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions). 3352bde8e466a4451c7319e3a072d118917957d6554Steve Block Label arityCheck = label(); 3362bde8e466a4451c7319e3a072d118917957d6554Steve Block preserveReturnAddressAfterCall(regT2); 3372bde8e466a4451c7319e3a072d118917957d6554Steve Block emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC); 3382bde8e466a4451c7319e3a072d118917957d6554Steve Block branch32(Equal, regT1, Imm32(m_codeBlock->m_numParameters)).linkTo(fromArityCheck, this); 3392bde8e466a4451c7319e3a072d118917957d6554Steve Block move(stackPointerRegister, argumentRegister0); 3402bde8e466a4451c7319e3a072d118917957d6554Steve Block poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); 3412bde8e466a4451c7319e3a072d118917957d6554Steve Block Call callArityCheck = call(); 3422bde8e466a4451c7319e3a072d118917957d6554Steve Block move(regT0, callFrameRegister); 3432bde8e466a4451c7319e3a072d118917957d6554Steve Block jump(fromArityCheck); 3442bde8e466a4451c7319e3a072d118917957d6554Steve Block 3452bde8e466a4451c7319e3a072d118917957d6554Steve Block 3462bde8e466a4451c7319e3a072d118917957d6554Steve Block // === Stage 4 - Link === 3472bde8e466a4451c7319e3a072d118917957d6554Steve Block // 3482bde8e466a4451c7319e3a072d118917957d6554Steve Block // Link the code, populate data in CodeBlock data structures. 3492bde8e466a4451c7319e3a072d118917957d6554Steve Block 3502bde8e466a4451c7319e3a072d118917957d6554Steve Block LinkBuffer linkBuffer(this, m_globalData->executableAllocator.poolForSize(m_assembler.size()), 0); 3512bde8e466a4451c7319e3a072d118917957d6554Steve Block 3522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if DFG_DEBUG_VERBOSE 3532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch fprintf(stderr, "JIT code start at %p\n", linkBuffer.debugAddress()); 3542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif 3552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 3562bde8e466a4451c7319e3a072d118917957d6554Steve Block // Link all calls out from the JIT code to their respective functions. 3572bde8e466a4451c7319e3a072d118917957d6554Steve Block for (unsigned i = 0; i < m_calls.size(); ++i) 3582bde8e466a4451c7319e3a072d118917957d6554Steve Block linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function); 3592bde8e466a4451c7319e3a072d118917957d6554Steve Block 3602bde8e466a4451c7319e3a072d118917957d6554Steve Block if (m_codeBlock->needsCallReturnIndices()) { 3612bde8e466a4451c7319e3a072d118917957d6554Steve Block m_codeBlock->callReturnIndexVector().reserveCapacity(exceptionCheckCount); 3622bde8e466a4451c7319e3a072d118917957d6554Steve Block for (unsigned i = 0; i < m_calls.size(); ++i) { 3632bde8e466a4451c7319e3a072d118917957d6554Steve Block if (m_calls[i].m_exceptionCheck.isSet()) { 3642bde8e466a4451c7319e3a072d118917957d6554Steve Block unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_calls[i].m_call); 3652bde8e466a4451c7319e3a072d118917957d6554Steve Block unsigned exceptionInfo = m_calls[i].m_exceptionInfo; 3662bde8e466a4451c7319e3a072d118917957d6554Steve Block m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo)); 3672bde8e466a4451c7319e3a072d118917957d6554Steve Block } 3682bde8e466a4451c7319e3a072d118917957d6554Steve Block } 3692bde8e466a4451c7319e3a072d118917957d6554Steve Block } 3702bde8e466a4451c7319e3a072d118917957d6554Steve Block 3712bde8e466a4451c7319e3a072d118917957d6554Steve Block // FIXME: switch the register file check & arity check over to DFGOpertaion style calls, not JIT stubs. 3722bde8e466a4451c7319e3a072d118917957d6554Steve Block linkBuffer.link(callRegisterFileCheck, cti_register_file_check); 3732bde8e466a4451c7319e3a072d118917957d6554Steve Block linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck); 3742bde8e466a4451c7319e3a072d118917957d6554Steve Block 3752bde8e466a4451c7319e3a072d118917957d6554Steve Block entryWithArityCheck = linkBuffer.locationOf(arityCheck); 3762bde8e466a4451c7319e3a072d118917957d6554Steve Block entry = linkBuffer.finalizeCode(); 3772bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3782bde8e466a4451c7319e3a072d118917957d6554Steve Block 3792bde8e466a4451c7319e3a072d118917957d6554Steve Block#if DFG_JIT_ASSERT 3802bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::jitAssertIsInt32(GPRReg gpr) 3812bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 3822bde8e466a4451c7319e3a072d118917957d6554Steve Block#if CPU(X86_64) 3832bde8e466a4451c7319e3a072d118917957d6554Steve Block Jump checkInt32 = branchPtr(BelowOrEqual, gprToRegisterID(gpr), TrustedImmPtr(reinterpret_cast<void*>(static_cast<uintptr_t>(0xFFFFFFFFu)))); 3842bde8e466a4451c7319e3a072d118917957d6554Steve Block breakpoint(); 3852bde8e466a4451c7319e3a072d118917957d6554Steve Block checkInt32.link(this); 3862bde8e466a4451c7319e3a072d118917957d6554Steve Block#else 3872bde8e466a4451c7319e3a072d118917957d6554Steve Block UNUSED_PARAM(gpr); 3882bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 3892bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3902bde8e466a4451c7319e3a072d118917957d6554Steve Block 3912bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::jitAssertIsJSInt32(GPRReg gpr) 3922bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 3932bde8e466a4451c7319e3a072d118917957d6554Steve Block Jump checkJSInt32 = branchPtr(AboveOrEqual, gprToRegisterID(gpr), tagTypeNumberRegister); 3942bde8e466a4451c7319e3a072d118917957d6554Steve Block breakpoint(); 3952bde8e466a4451c7319e3a072d118917957d6554Steve Block checkJSInt32.link(this); 3962bde8e466a4451c7319e3a072d118917957d6554Steve Block} 3972bde8e466a4451c7319e3a072d118917957d6554Steve Block 3982bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::jitAssertIsJSNumber(GPRReg gpr) 3992bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4002bde8e466a4451c7319e3a072d118917957d6554Steve Block Jump checkJSNumber = branchTestPtr(MacroAssembler::NonZero, gprToRegisterID(gpr), tagTypeNumberRegister); 4012bde8e466a4451c7319e3a072d118917957d6554Steve Block breakpoint(); 4022bde8e466a4451c7319e3a072d118917957d6554Steve Block checkJSNumber.link(this); 4032bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4042bde8e466a4451c7319e3a072d118917957d6554Steve Block 4052bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::jitAssertIsJSDouble(GPRReg gpr) 4062bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4072bde8e466a4451c7319e3a072d118917957d6554Steve Block Jump checkJSInt32 = branchPtr(AboveOrEqual, gprToRegisterID(gpr), tagTypeNumberRegister); 4082bde8e466a4451c7319e3a072d118917957d6554Steve Block Jump checkJSNumber = branchTestPtr(MacroAssembler::NonZero, gprToRegisterID(gpr), tagTypeNumberRegister); 4092bde8e466a4451c7319e3a072d118917957d6554Steve Block checkJSInt32.link(this); 4102bde8e466a4451c7319e3a072d118917957d6554Steve Block breakpoint(); 4112bde8e466a4451c7319e3a072d118917957d6554Steve Block checkJSNumber.link(this); 4122bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4132bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 4142bde8e466a4451c7319e3a072d118917957d6554Steve Block 4152bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(SAMPLING_COUNTERS) && CPU(X86_64) // Or any other 64-bit platform! 4162bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::emitCount(AbstractSamplingCounter& counter, uint32_t increment) 4172bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4182bde8e466a4451c7319e3a072d118917957d6554Steve Block addPtr(TrustedImm32(increment), AbsoluteAddress(counter.addressOfCounter())); 4192bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4202bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 4212bde8e466a4451c7319e3a072d118917957d6554Steve Block 4222bde8e466a4451c7319e3a072d118917957d6554Steve Block#if ENABLE(SAMPLING_COUNTERS) && CPU(X86) // Or any other little-endian 32-bit platform! 4232bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid JITCompiler::emitCount(AbstractSamplingCounter& counter, uint32_t increment) 4242bde8e466a4451c7319e3a072d118917957d6554Steve Block{ 4252bde8e466a4451c7319e3a072d118917957d6554Steve Block intptr_t hiWord = reinterpret_cast<intptr_t>(counter.addressOfCounter()) + sizeof(int32_t); 4262bde8e466a4451c7319e3a072d118917957d6554Steve Block add32(TrustedImm32(increment), AbsoluteAddress(counter.addressOfCounter())); 4272bde8e466a4451c7319e3a072d118917957d6554Steve Block addWithCarry32(TrustedImm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord))); 4282bde8e466a4451c7319e3a072d118917957d6554Steve Block} 4292bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 4302bde8e466a4451c7319e3a072d118917957d6554Steve Block 4312bde8e466a4451c7319e3a072d118917957d6554Steve Block} } // namespace JSC::DFG 4322bde8e466a4451c7319e3a072d118917957d6554Steve Block 4332bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif 434