X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/1df5f87f1309a8daa30dabdee855f48ae40d14ab..6fe7ccc865dc7d7541b93c5bcaf6368d2c98a174:/dfg/DFGJITCodeGenerator.cpp?ds=sidebyside diff --git a/dfg/DFGJITCodeGenerator.cpp b/dfg/DFGJITCodeGenerator.cpp deleted file mode 100644 index 781edbb..0000000 --- a/dfg/DFGJITCodeGenerator.cpp +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Copyright (C) 2011 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 "DFGJITCodeGenerator.h" - -#if ENABLE(DFG_JIT) - -#include "DFGNonSpeculativeJIT.h" -#include "DFGSpeculativeJIT.h" -#include "LinkBuffer.h" - -namespace JSC { namespace DFG { - -GPRReg JITCodeGenerator::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat) -{ - Node& node = m_jit.graph()[nodeIndex]; - VirtualRegister virtualRegister = node.virtualRegister(); - GenerationInfo& info = m_generationInfo[virtualRegister]; - - if (info.registerFormat() == DataFormatNone) { - GPRReg gpr = allocate(); - - if (node.isConstant()) { - m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); - if (isInt32Constant(nodeIndex)) { - m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr); - info.fillInteger(gpr); - returnFormat = DataFormatInteger; - return gpr; - } - if (isDoubleConstant(nodeIndex)) { - JSValue jsValue = jsNumber(valueOfDoubleConstant(nodeIndex)); - m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr); - } else { - ASSERT(isJSConstant(nodeIndex)); - JSValue jsValue = valueOfJSConstant(nodeIndex); - m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr); - } - } else { - ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger); - m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); - m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr); - } - - // Since we statically know that we're filling an integer, and values - // in the RegisterFile are boxed, this must be DataFormatJSInteger. - // We will check this with a jitAssert below. - info.fillJSValue(gpr, DataFormatJSInteger); - unlock(gpr); - } - - switch (info.registerFormat()) { - case DataFormatNone: - // Should have filled, above. - case DataFormatJSDouble: - case DataFormatDouble: - case DataFormatJS: - case DataFormatCell: - case DataFormatJSCell: - // Should only be calling this function if we know this operand to be integer. - ASSERT_NOT_REACHED(); - - case DataFormatJSInteger: { - GPRReg gpr = info.gpr(); - m_gprs.lock(gpr); - m_jit.jitAssertIsJSInt32(gpr); - returnFormat = DataFormatJSInteger; - return gpr; - } - - case DataFormatInteger: { - GPRReg gpr = info.gpr(); - m_gprs.lock(gpr); - m_jit.jitAssertIsInt32(gpr); - returnFormat = DataFormatInteger; - return gpr; - } - } - - ASSERT_NOT_REACHED(); - return InvalidGPRReg; -} - -FPRReg JITCodeGenerator::fillDouble(NodeIndex nodeIndex) -{ - Node& node = m_jit.graph()[nodeIndex]; - VirtualRegister virtualRegister = node.virtualRegister(); - GenerationInfo& info = m_generationInfo[virtualRegister]; - - if (info.registerFormat() == DataFormatNone) { - GPRReg gpr = allocate(); - - if (node.isConstant()) { - if (isInt32Constant(nodeIndex)) { - // FIXME: should not be reachable? - m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr); - m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); - info.fillInteger(gpr); - unlock(gpr); - } else if (isDoubleConstant(nodeIndex)) { - FPRReg fpr = fprAllocate(); - m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), gpr); - m_jit.movePtrToDouble(gpr, fpr); - unlock(gpr); - - m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); - info.fillDouble(fpr); - return fpr; - } else { - // FIXME: should not be reachable? - ASSERT(isJSConstant(nodeIndex)); - JSValue jsValue = valueOfJSConstant(nodeIndex); - m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr); - m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); - info.fillJSValue(gpr, DataFormatJS); - unlock(gpr); - } - } else { - DataFormat spillFormat = info.spillFormat(); - ASSERT(spillFormat & DataFormatJS); - m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); - m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr); - info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS); - unlock(gpr); - } - } - - switch (info.registerFormat()) { - case DataFormatNone: - // Should have filled, above. - case DataFormatCell: - case DataFormatJSCell: - // Should only be calling this function if we know this operand to be numeric. - ASSERT_NOT_REACHED(); - - case DataFormatJS: { - GPRReg jsValueGpr = info.gpr(); - m_gprs.lock(jsValueGpr); - FPRReg fpr = fprAllocate(); - GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register? - - JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister); - - m_jit.jitAssertIsJSDouble(jsValueGpr); - - // First, if we get here we have a double encoded as a JSValue - m_jit.move(jsValueGpr, tempGpr); - m_jit.addPtr(GPRInfo::tagTypeNumberRegister, tempGpr); - m_jit.movePtrToDouble(tempGpr, fpr); - JITCompiler::Jump hasUnboxedDouble = m_jit.jump(); - - // Finally, handle integers. - isInteger.link(&m_jit); - m_jit.convertInt32ToDouble(jsValueGpr, fpr); - hasUnboxedDouble.link(&m_jit); - - m_gprs.release(jsValueGpr); - m_gprs.unlock(jsValueGpr); - m_gprs.unlock(tempGpr); - m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); - info.fillDouble(fpr); - return fpr; - } - - case DataFormatJSInteger: - case DataFormatInteger: { - FPRReg fpr = fprAllocate(); - GPRReg gpr = info.gpr(); - m_gprs.lock(gpr); - - m_jit.convertInt32ToDouble(gpr, fpr); - - m_gprs.release(gpr); - m_gprs.unlock(gpr); - m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); - info.fillDouble(fpr); - return fpr; - } - - // Unbox the double - case DataFormatJSDouble: { - GPRReg gpr = info.gpr(); - FPRReg fpr = unboxDouble(gpr); - - m_gprs.release(gpr); - m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); - - info.fillDouble(fpr); - return fpr; - } - - case DataFormatDouble: { - FPRReg fpr = info.fpr(); - m_fprs.lock(fpr); - return fpr; - } - } - - ASSERT_NOT_REACHED(); - return InvalidFPRReg; -} - -GPRReg JITCodeGenerator::fillJSValue(NodeIndex nodeIndex) -{ - Node& node = m_jit.graph()[nodeIndex]; - VirtualRegister virtualRegister = node.virtualRegister(); - GenerationInfo& info = m_generationInfo[virtualRegister]; - - switch (info.registerFormat()) { - case DataFormatNone: { - GPRReg gpr = allocate(); - - if (node.isConstant()) { - if (isInt32Constant(nodeIndex)) { - info.fillJSValue(gpr, DataFormatJSInteger); - JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex)); - m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr); - } else if (isDoubleConstant(nodeIndex)) { - info.fillJSValue(gpr, DataFormatJSDouble); - JSValue jsValue(JSValue::EncodeAsDouble, valueOfDoubleConstant(nodeIndex)); - m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr); - } else { - ASSERT(isJSConstant(nodeIndex)); - JSValue jsValue = valueOfJSConstant(nodeIndex); - m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr); - info.fillJSValue(gpr, DataFormatJS); - } - - m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); - } else { - DataFormat spillFormat = info.spillFormat(); - ASSERT(spillFormat & DataFormatJS); - m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); - m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr); - info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS); - } - return gpr; - } - - case DataFormatInteger: { - GPRReg gpr = info.gpr(); - // If the register has already been locked we need to take a copy. - // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger. - if (m_gprs.isLocked(gpr)) { - GPRReg result = allocate(); - m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr, result); - return result; - } - m_gprs.lock(gpr); - m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr); - info.fillJSValue(gpr, DataFormatJSInteger); - return gpr; - } - - case DataFormatDouble: { - FPRReg fpr = info.fpr(); - GPRReg gpr = boxDouble(fpr); - - // Update all info - info.fillJSValue(gpr, DataFormatJSDouble); - m_fprs.release(fpr); - m_gprs.retain(gpr, virtualRegister, SpillOrderJS); - - return gpr; - } - - case DataFormatCell: - // No retag required on JSVALUE64! - case DataFormatJS: - case DataFormatJSInteger: - case DataFormatJSDouble: - case DataFormatJSCell: { - GPRReg gpr = info.gpr(); - m_gprs.lock(gpr); - return gpr; - } - } - - ASSERT_NOT_REACHED(); - return InvalidGPRReg; -} - -void JITCodeGenerator::useChildren(Node& node) -{ - NodeIndex child1 = node.child1; - if (child1 == NoNode) { - ASSERT(node.child2 == NoNode && node.child3 == NoNode); - return; - } - use(child1); - - NodeIndex child2 = node.child2; - if (child2 == NoNode) { - ASSERT(node.child3 == NoNode); - return; - } - use(child2); - - NodeIndex child3 = node.child3; - if (child3 == NoNode) - return; - use(child3); -} - -#ifndef NDEBUG -static const char* dataFormatString(DataFormat format) -{ - // These values correspond to the DataFormat enum. - const char* strings[] = { - "[ ]", - "[ i]", - "[ d]", - "[ c]", - "Err!", - "Err!", - "Err!", - "Err!", - "[J ]", - "[Ji]", - "[Jd]", - "[Jc]", - "Err!", - "Err!", - "Err!", - "Err!", - }; - return strings[format]; -} - -void JITCodeGenerator::dump(const char* label) -{ - if (label) - fprintf(stderr, "<%s>\n", label); - - fprintf(stderr, " gprs:\n"); - m_gprs.dump(); - fprintf(stderr, " fprs:\n"); - m_fprs.dump(); - fprintf(stderr, " VirtualRegisters:\n"); - for (unsigned i = 0; i < m_generationInfo.size(); ++i) { - GenerationInfo& info = m_generationInfo[i]; - if (info.alive()) - fprintf(stderr, " % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat())); - else - fprintf(stderr, " % 3d:[__][__]", i); - if (info.registerFormat() == DataFormatDouble) - fprintf(stderr, ":fpr%d\n", info.fpr()); - else if (info.registerFormat() != DataFormatNone) { - ASSERT(info.gpr() != InvalidGPRReg); - fprintf(stderr, ":%s\n", GPRInfo::debugName(info.gpr())); - } else - fprintf(stderr, "\n"); - } - if (label) - fprintf(stderr, "\n", label); -} -#endif - - -#if DFG_CONSISTENCY_CHECK -void JITCodeGenerator::checkConsistency() -{ - bool failed = false; - - for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) { - if (iter.isLocked()) { - fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName()); - failed = true; - } - } - for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) { - if (iter.isLocked()) { - fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName()); - failed = true; - } - } - - for (unsigned i = 0; i < m_generationInfo.size(); ++i) { - VirtualRegister virtualRegister = (VirtualRegister)i; - GenerationInfo& info = m_generationInfo[virtualRegister]; - if (!info.alive()) - continue; - switch (info.registerFormat()) { - case DataFormatNone: - break; - case DataFormatInteger: - case DataFormatCell: - case DataFormatJS: - case DataFormatJSInteger: - case DataFormatJSDouble: - case DataFormatJSCell: { - GPRReg gpr = info.gpr(); - ASSERT(gpr != InvalidGPRReg); - if (m_gprs.name(gpr) != virtualRegister) { - fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr)); - failed = true; - } - break; - } - case DataFormatDouble: { - FPRReg fpr = info.fpr(); - ASSERT(fpr != InvalidFPRReg); - if (m_fprs.name(fpr) != virtualRegister) { - fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr)); - failed = true; - } - break; - } - } - } - - for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) { - VirtualRegister virtualRegister = iter.name(); - if (virtualRegister == InvalidVirtualRegister) - continue; - - GenerationInfo& info = m_generationInfo[virtualRegister]; - if (iter.regID() != info.gpr()) { - fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister); - failed = true; - } - } - - for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) { - VirtualRegister virtualRegister = iter.name(); - if (virtualRegister == InvalidVirtualRegister) - continue; - - GenerationInfo& info = m_generationInfo[virtualRegister]; - if (iter.regID() != info.fpr()) { - fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister); - failed = true; - } - } - - if (failed) { - dump(); - CRASH(); - } -} -#endif - -GPRTemporary::GPRTemporary(JITCodeGenerator* jit) - : m_jit(jit) - , m_gpr(InvalidGPRReg) -{ - m_gpr = m_jit->allocate(); -} - -GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1) - : m_jit(jit) - , m_gpr(InvalidGPRReg) -{ - if (m_jit->canReuse(op1.index())) - m_gpr = m_jit->reuse(op1.gpr()); - else - m_gpr = m_jit->allocate(); -} - -GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2) - : m_jit(jit) - , m_gpr(InvalidGPRReg) -{ - if (m_jit->canReuse(op1.index())) - m_gpr = m_jit->reuse(op1.gpr()); - else if (m_jit->canReuse(op2.index())) - m_gpr = m_jit->reuse(op2.gpr()); - else - m_gpr = m_jit->allocate(); -} - -GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1) - : m_jit(jit) - , m_gpr(InvalidGPRReg) -{ - if (m_jit->canReuse(op1.index())) - m_gpr = m_jit->reuse(op1.gpr()); - else - m_gpr = m_jit->allocate(); -} - -GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1, IntegerOperand& op2) - : m_jit(jit) - , m_gpr(InvalidGPRReg) -{ - if (m_jit->canReuse(op1.index())) - m_gpr = m_jit->reuse(op1.gpr()); - else if (m_jit->canReuse(op2.index())) - m_gpr = m_jit->reuse(op2.gpr()); - else - m_gpr = m_jit->allocate(); -} - -GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateCellOperand& op1) - : m_jit(jit) - , m_gpr(InvalidGPRReg) -{ - if (m_jit->canReuse(op1.index())) - m_gpr = m_jit->reuse(op1.gpr()); - else - m_gpr = m_jit->allocate(); -} - -GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1) - : m_jit(jit) - , m_gpr(InvalidGPRReg) -{ - if (m_jit->canReuse(op1.index())) - m_gpr = m_jit->reuse(op1.gpr()); - else - m_gpr = m_jit->allocate(); -} - -FPRTemporary::FPRTemporary(JITCodeGenerator* jit) - : m_jit(jit) - , m_fpr(InvalidFPRReg) -{ - m_fpr = m_jit->fprAllocate(); -} - -FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1) - : m_jit(jit) - , m_fpr(InvalidFPRReg) -{ - if (m_jit->canReuse(op1.index())) - m_fpr = m_jit->reuse(op1.fpr()); - else - m_fpr = m_jit->fprAllocate(); -} - -FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1, DoubleOperand& op2) - : m_jit(jit) - , m_fpr(InvalidFPRReg) -{ - if (m_jit->canReuse(op1.index())) - m_fpr = m_jit->reuse(op1.fpr()); - else if (m_jit->canReuse(op2.index())) - m_fpr = m_jit->reuse(op2.fpr()); - else - m_fpr = m_jit->fprAllocate(); -} - -} } // namespace JSC::DFG - -#endif