Commit d910c0d8 authored by barraclough@apple.com's avatar barraclough@apple.com

Add JSVALUE32_64 support to DFG JIT

https://bugs.webkit.org/show_bug.cgi?id=67460

Patch by Yuqiang Xian <yuqiang.xian@intel.com> on 2011-09-23
Reviewed by Gavin Barraclough.

This is the initial attempt to add JSVALUE32_64 support to DFG JIT.
It's tested on IA32 Linux EFL port currently. It still cannot run
all the test cases and benchmarks so should be turned off now.
        
The major work includes:
1) dealing with JSVALUE32_64 data format in DFG JIT;
2) bindings between 64-bit JS Value and 32-bit registers;
3) handling of function calls. Currently for DFG operation function
calls we follow the X86 cdecl calling convention on Linux, and the
implementation is in a naive way by pushing the arguments into stack
one by one.
        
The known issues include:
1) some code duplicates unnecessarily, especially in Speculative JIT
code generation, where most of the operations on SpeculataInteger /
SpeculateDouble should be identical to the JSVALUE64 code. Refactoring
is needed in the future;
2) lack of op_call and op_construct support, comparing to current
JSVALUE64 DFG;
3) currently integer speculations assume to be StrictInt32;
4) lack of JSBoolean speculations;
5) boxing and unboxing doubles could be improved;
6) DFG X86 register description is different with the baseline JIT,
the timeoutCheckRegister is used for general purpose usage;
7) calls to runtime functions with primitive double parameters (e.g.
fmod) don't work. Support needs to be added to the assembler to
implement the mechanism of passing double parameters for X86 cdecl
convention.
        
And there should be many other hidden bugs which should be exposed and
resolved in later debugging process.

* CMakeListsEfl.txt:
* assembler/MacroAssemblerX86.h:
(JSC::MacroAssemblerX86::loadDouble):
(JSC::MacroAssemblerX86::storeDouble):
* assembler/X86Assembler.h:
(JSC::X86Assembler::movsd_rm):
* bytecode/StructureStubInfo.h:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.h:
(JSC::DFG::canCompileOpcode):
* dfg/DFGFPRInfo.h:
(JSC::DFG::FPRInfo::debugName):
* dfg/DFGGPRInfo.h:
(JSC::DFG::GPRInfo::toRegister):
(JSC::DFG::GPRInfo::toIndex):
(JSC::DFG::GPRInfo::debugName):
* dfg/DFGGenerationInfo.h:
(JSC::DFG::needDataFormatConversion):
(JSC::DFG::GenerationInfo::initJSValue):
(JSC::DFG::GenerationInfo::initDouble):
(JSC::DFG::GenerationInfo::gpr):
(JSC::DFG::GenerationInfo::tagGPR):
(JSC::DFG::GenerationInfo::payloadGPR):
(JSC::DFG::GenerationInfo::fpr):
(JSC::DFG::GenerationInfo::fillJSValue):
(JSC::DFG::GenerationInfo::fillCell):
(JSC::DFG::GenerationInfo::fillDouble):
* dfg/DFGJITCodeGenerator.cpp:
* dfg/DFGJITCodeGenerator.h:
(JSC::DFG::JITCodeGenerator::allocate):
(JSC::DFG::JITCodeGenerator::use):
(JSC::DFG::JITCodeGenerator::registersMatched):
(JSC::DFG::JITCodeGenerator::silentSpillGPR):
(JSC::DFG::JITCodeGenerator::silentFillGPR):
(JSC::DFG::JITCodeGenerator::silentFillFPR):
(JSC::DFG::JITCodeGenerator::silentSpillAllRegisters):
(JSC::DFG::JITCodeGenerator::silentFillAllRegisters):
(JSC::DFG::JITCodeGenerator::boxDouble):
(JSC::DFG::JITCodeGenerator::unboxDouble):
(JSC::DFG::JITCodeGenerator::spill):
(JSC::DFG::addressOfDoubleConstant):
(JSC::DFG::integerResult):
(JSC::DFG::jsValueResult):
(JSC::DFG::setupResults):
(JSC::DFG::callOperation):
(JSC::JSValueOperand::JSValueOperand):
(JSC::JSValueOperand::~JSValueOperand):
(JSC::JSValueOperand::isDouble):
(JSC::JSValueOperand::fill):
(JSC::JSValueOperand::tagGPR):
(JSC::JSValueOperand::payloadGPR):
(JSC::JSValueOperand::fpr):
(JSC::GPRTemporary::~GPRTemporary):
(JSC::GPRTemporary::gpr):
(JSC::GPRResult2::GPRResult2):
* dfg/DFGJITCodeGenerator32_64.cpp: Added.
(JSC::DFG::JITCodeGenerator::clearGenerationInfo):
(JSC::DFG::JITCodeGenerator::fillInteger):
(JSC::DFG::JITCodeGenerator::fillDouble):
(JSC::DFG::JITCodeGenerator::fillJSValue):
(JSC::DFG::JITCodeGenerator::fillStorage):
(JSC::DFG::JITCodeGenerator::useChildren):
(JSC::DFG::JITCodeGenerator::isStrictInt32):
(JSC::DFG::JITCodeGenerator::isKnownInteger):
(JSC::DFG::JITCodeGenerator::isKnownNumeric):
(JSC::DFG::JITCodeGenerator::isKnownCell):
(JSC::DFG::JITCodeGenerator::isKnownNotInteger):
(JSC::DFG::JITCodeGenerator::isKnownNotNumber):
(JSC::DFG::JITCodeGenerator::isKnownBoolean):
(JSC::DFG::JITCodeGenerator::nonSpeculativeValueToNumber):
(JSC::DFG::JITCodeGenerator::nonSpeculativeValueToInt32):
(JSC::DFG::JITCodeGenerator::nonSpeculativeUInt32ToNumber):
(JSC::DFG::JITCodeGenerator::nonSpeculativeKnownConstantArithOp):
(JSC::DFG::JITCodeGenerator::nonSpeculativeBasicArithOp):
(JSC::DFG::JITCodeGenerator::nonSpeculativeArithMod):
(JSC::DFG::JITCodeGenerator::nonSpeculativeCheckHasInstance):
(JSC::DFG::JITCodeGenerator::nonSpeculativeInstanceOf):
(JSC::DFG::JITCodeGenerator::cachedGetById):
(JSC::DFG::JITCodeGenerator::writeBarrier):
(JSC::DFG::JITCodeGenerator::cachedPutById):
(JSC::DFG::JITCodeGenerator::cachedGetMethod):
(JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeCompareNull):
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranchNull):
(JSC::DFG::JITCodeGenerator::nonSpeculativeCompareNull):
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranch):
(JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeCompare):
(JSC::DFG::JITCodeGenerator::nonSpeculativeCompare):
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeStrictEq):
(JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq):
(JSC::DFG::JITCodeGenerator::nonSpeculativeStrictEq):
(JSC::DFG::JITCodeGenerator::emitBranch):
(JSC::DFG::JITCodeGenerator::nonSpeculativeLogicalNot):
(JSC::DFG::JITCodeGenerator::emitCall):
(JSC::DFG::JITCodeGenerator::speculationCheck):
(JSC::DFG::dataFormatString):
(JSC::DFG::JITCodeGenerator::dump):
(JSC::DFG::JITCodeGenerator::checkConsistency):
(JSC::DFG::GPRTemporary::GPRTemporary):
(JSC::DFG::FPRTemporary::FPRTemporary):
* dfg/DFGJITCompiler.cpp:
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::tagForGlobalVar):
(JSC::DFG::JITCompiler::payloadForGlobalVar):
(JSC::DFG::JITCompiler::appendCallWithExceptionCheck):
(JSC::DFG::JITCompiler::addressOfDoubleConstant):
(JSC::DFG::JITCompiler::boxDouble):
(JSC::DFG::JITCompiler::unboxDouble):
(JSC::DFG::JITCompiler::addPropertyAccess):
(JSC::DFG::JITCompiler::PropertyAccessRecord::PropertyAccessRecord):
* dfg/DFGJITCompiler32_64.cpp: Added.
(JSC::DFG::JITCompiler::fillNumericToDouble):
(JSC::DFG::JITCompiler::fillInt32ToInteger):
(JSC::DFG::JITCompiler::fillToJS):
(JSC::DFG::JITCompiler::exitSpeculativeWithOSR):
(JSC::DFG::JITCompiler::linkOSRExits):
(JSC::DFG::JITCompiler::compileEntry):
(JSC::DFG::JITCompiler::compileBody):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
(JSC::DFG::JITCompiler::jitAssertIsInt32):
(JSC::DFG::JITCompiler::jitAssertIsJSInt32):
(JSC::DFG::JITCompiler::jitAssertIsJSNumber):
(JSC::DFG::JITCompiler::jitAssertIsJSDouble):
(JSC::DFG::JITCompiler::jitAssertIsCell):
(JSC::DFG::JITCompiler::emitCount):
(JSC::DFG::JITCompiler::setSamplingFlag):
(JSC::DFG::JITCompiler::clearSamplingFlag):
* dfg/DFGJITCompilerInlineMethods.h: Added.
(JSC::DFG::JITCompiler::emitLoadTag):
(JSC::DFG::JITCompiler::emitLoadPayload):
(JSC::DFG::JITCompiler::emitLoad):
(JSC::DFG::JITCompiler::emitLoad2):
(JSC::DFG::JITCompiler::emitLoadDouble):
(JSC::DFG::JITCompiler::emitLoadInt32ToDouble):
(JSC::DFG::JITCompiler::emitStore):
(JSC::DFG::JITCompiler::emitStoreInt32):
(JSC::DFG::JITCompiler::emitStoreCell):
(JSC::DFG::JITCompiler::emitStoreBool):
(JSC::DFG::JITCompiler::emitStoreDouble):
* dfg/DFGNode.h:
* dfg/DFGOperations.cpp:
* dfg/DFGRepatch.cpp:
(JSC::DFG::generateProtoChainAccessStub):
(JSC::DFG::tryCacheGetByID):
(JSC::DFG::tryBuildGetByIDList):
(JSC::DFG::tryCachePutByID):
* dfg/DFGSpeculativeJIT.cpp:
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::ValueRecovery::inGPR):
(JSC::DFG::ValueRecovery::inPair):
(JSC::DFG::ValueRecovery::tagGPR):
(JSC::DFG::ValueRecovery::payloadGPR):
* dfg/DFGSpeculativeJIT32_64.cpp: Added.
(JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
(JSC::DFG::ValueSource::dump):
(JSC::DFG::ValueRecovery::dump):
(JSC::DFG::OSRExit::OSRExit):
(JSC::DFG::OSRExit::dump):
(JSC::DFG::SpeculativeJIT::fillSpeculateInt):
(JSC::DFG::SpeculativeJIT::fillSpeculateIntStrict):
(JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
(JSC::DFG::SpeculativeJIT::compilePeepHoleIntegerBranch):
(JSC::DFG::SpeculativeJIT::convertToDouble):
(JSC::DFG::SpeculativeJIT::compilePeepHoleDoubleBranch):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compare):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileMovHint):
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::initializeVariableTypes):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
* runtime/JSValue.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@95902 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 2919d671
......@@ -16,3 +16,25 @@ ENDIF ()
LIST(APPEND JavaScriptCore_LINK_FLAGS
${ECORE_LDFLAGS}
)
IF (ENABLE_DFG_JIT)
LIST(APPEND JavaScriptCore_INCLUDE_DIRECTORIES
${JAVASCRIPTCORE_DIR}/dfg
)
LIST(APPEND JavaScriptCore_SOURCES
dfg/DFGByteCodeParser.cpp
dfg/DFGCapabilities.cpp
dfg/DFGDriver.cpp
dfg/DFGGraph.cpp
dfg/DFGJITCodeGenerator.cpp
dfg/DFGJITCodeGenerator32_64.cpp
dfg/DFGJITCompiler.cpp
dfg/DFGJITCompiler32_64.cpp
dfg/DFGOperations.cpp
dfg/DFGOSREntry.cpp
dfg/DFGPropagator.cpp
dfg/DFGRepatch.cpp
dfg/DFGSpeculativeJIT.cpp
dfg/DFGSpeculativeJIT32_64.cpp
)
ENDIF ()
2011-09-23 Yuqiang Xian <yuqiang.xian@intel.com>
Add JSVALUE32_64 support to DFG JIT
https://bugs.webkit.org/show_bug.cgi?id=67460
Reviewed by Gavin Barraclough.
This is the initial attempt to add JSVALUE32_64 support to DFG JIT.
It's tested on IA32 Linux EFL port currently. It still cannot run
all the test cases and benchmarks so should be turned off now.
The major work includes:
1) dealing with JSVALUE32_64 data format in DFG JIT;
2) bindings between 64-bit JS Value and 32-bit registers;
3) handling of function calls. Currently for DFG operation function
calls we follow the X86 cdecl calling convention on Linux, and the
implementation is in a naive way by pushing the arguments into stack
one by one.
The known issues include:
1) some code duplicates unnecessarily, especially in Speculative JIT
code generation, where most of the operations on SpeculataInteger /
SpeculateDouble should be identical to the JSVALUE64 code. Refactoring
is needed in the future;
2) lack of op_call and op_construct support, comparing to current
JSVALUE64 DFG;
3) currently integer speculations assume to be StrictInt32;
4) lack of JSBoolean speculations;
5) boxing and unboxing doubles could be improved;
6) DFG X86 register description is different with the baseline JIT,
the timeoutCheckRegister is used for general purpose usage;
7) calls to runtime functions with primitive double parameters (e.g.
fmod) don't work. Support needs to be added to the assembler to
implement the mechanism of passing double parameters for X86 cdecl
convention.
And there should be many other hidden bugs which should be exposed and
resolved in later debugging process.
* CMakeListsEfl.txt:
* assembler/MacroAssemblerX86.h:
(JSC::MacroAssemblerX86::loadDouble):
(JSC::MacroAssemblerX86::storeDouble):
* assembler/X86Assembler.h:
(JSC::X86Assembler::movsd_rm):
* bytecode/StructureStubInfo.h:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.h:
(JSC::DFG::canCompileOpcode):
* dfg/DFGFPRInfo.h:
(JSC::DFG::FPRInfo::debugName):
* dfg/DFGGPRInfo.h:
(JSC::DFG::GPRInfo::toRegister):
(JSC::DFG::GPRInfo::toIndex):
(JSC::DFG::GPRInfo::debugName):
* dfg/DFGGenerationInfo.h:
(JSC::DFG::needDataFormatConversion):
(JSC::DFG::GenerationInfo::initJSValue):
(JSC::DFG::GenerationInfo::initDouble):
(JSC::DFG::GenerationInfo::gpr):
(JSC::DFG::GenerationInfo::tagGPR):
(JSC::DFG::GenerationInfo::payloadGPR):
(JSC::DFG::GenerationInfo::fpr):
(JSC::DFG::GenerationInfo::fillJSValue):
(JSC::DFG::GenerationInfo::fillCell):
(JSC::DFG::GenerationInfo::fillDouble):
* dfg/DFGJITCodeGenerator.cpp:
* dfg/DFGJITCodeGenerator.h:
(JSC::DFG::JITCodeGenerator::allocate):
(JSC::DFG::JITCodeGenerator::use):
(JSC::DFG::JITCodeGenerator::registersMatched):
(JSC::DFG::JITCodeGenerator::silentSpillGPR):
(JSC::DFG::JITCodeGenerator::silentFillGPR):
(JSC::DFG::JITCodeGenerator::silentFillFPR):
(JSC::DFG::JITCodeGenerator::silentSpillAllRegisters):
(JSC::DFG::JITCodeGenerator::silentFillAllRegisters):
(JSC::DFG::JITCodeGenerator::boxDouble):
(JSC::DFG::JITCodeGenerator::unboxDouble):
(JSC::DFG::JITCodeGenerator::spill):
(JSC::DFG::addressOfDoubleConstant):
(JSC::DFG::integerResult):
(JSC::DFG::jsValueResult):
(JSC::DFG::setupResults):
(JSC::DFG::callOperation):
(JSC::JSValueOperand::JSValueOperand):
(JSC::JSValueOperand::~JSValueOperand):
(JSC::JSValueOperand::isDouble):
(JSC::JSValueOperand::fill):
(JSC::JSValueOperand::tagGPR):
(JSC::JSValueOperand::payloadGPR):
(JSC::JSValueOperand::fpr):
(JSC::GPRTemporary::~GPRTemporary):
(JSC::GPRTemporary::gpr):
(JSC::GPRResult2::GPRResult2):
* dfg/DFGJITCodeGenerator32_64.cpp: Added.
(JSC::DFG::JITCodeGenerator::clearGenerationInfo):
(JSC::DFG::JITCodeGenerator::fillInteger):
(JSC::DFG::JITCodeGenerator::fillDouble):
(JSC::DFG::JITCodeGenerator::fillJSValue):
(JSC::DFG::JITCodeGenerator::fillStorage):
(JSC::DFG::JITCodeGenerator::useChildren):
(JSC::DFG::JITCodeGenerator::isStrictInt32):
(JSC::DFG::JITCodeGenerator::isKnownInteger):
(JSC::DFG::JITCodeGenerator::isKnownNumeric):
(JSC::DFG::JITCodeGenerator::isKnownCell):
(JSC::DFG::JITCodeGenerator::isKnownNotInteger):
(JSC::DFG::JITCodeGenerator::isKnownNotNumber):
(JSC::DFG::JITCodeGenerator::isKnownBoolean):
(JSC::DFG::JITCodeGenerator::nonSpeculativeValueToNumber):
(JSC::DFG::JITCodeGenerator::nonSpeculativeValueToInt32):
(JSC::DFG::JITCodeGenerator::nonSpeculativeUInt32ToNumber):
(JSC::DFG::JITCodeGenerator::nonSpeculativeKnownConstantArithOp):
(JSC::DFG::JITCodeGenerator::nonSpeculativeBasicArithOp):
(JSC::DFG::JITCodeGenerator::nonSpeculativeArithMod):
(JSC::DFG::JITCodeGenerator::nonSpeculativeCheckHasInstance):
(JSC::DFG::JITCodeGenerator::nonSpeculativeInstanceOf):
(JSC::DFG::JITCodeGenerator::cachedGetById):
(JSC::DFG::JITCodeGenerator::writeBarrier):
(JSC::DFG::JITCodeGenerator::cachedPutById):
(JSC::DFG::JITCodeGenerator::cachedGetMethod):
(JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeCompareNull):
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranchNull):
(JSC::DFG::JITCodeGenerator::nonSpeculativeCompareNull):
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranch):
(JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeCompare):
(JSC::DFG::JITCodeGenerator::nonSpeculativeCompare):
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeStrictEq):
(JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq):
(JSC::DFG::JITCodeGenerator::nonSpeculativeStrictEq):
(JSC::DFG::JITCodeGenerator::emitBranch):
(JSC::DFG::JITCodeGenerator::nonSpeculativeLogicalNot):
(JSC::DFG::JITCodeGenerator::emitCall):
(JSC::DFG::JITCodeGenerator::speculationCheck):
(JSC::DFG::dataFormatString):
(JSC::DFG::JITCodeGenerator::dump):
(JSC::DFG::JITCodeGenerator::checkConsistency):
(JSC::DFG::GPRTemporary::GPRTemporary):
(JSC::DFG::FPRTemporary::FPRTemporary):
* dfg/DFGJITCompiler.cpp:
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::tagForGlobalVar):
(JSC::DFG::JITCompiler::payloadForGlobalVar):
(JSC::DFG::JITCompiler::appendCallWithExceptionCheck):
(JSC::DFG::JITCompiler::addressOfDoubleConstant):
(JSC::DFG::JITCompiler::boxDouble):
(JSC::DFG::JITCompiler::unboxDouble):
(JSC::DFG::JITCompiler::addPropertyAccess):
(JSC::DFG::JITCompiler::PropertyAccessRecord::PropertyAccessRecord):
* dfg/DFGJITCompiler32_64.cpp: Added.
(JSC::DFG::JITCompiler::fillNumericToDouble):
(JSC::DFG::JITCompiler::fillInt32ToInteger):
(JSC::DFG::JITCompiler::fillToJS):
(JSC::DFG::JITCompiler::exitSpeculativeWithOSR):
(JSC::DFG::JITCompiler::linkOSRExits):
(JSC::DFG::JITCompiler::compileEntry):
(JSC::DFG::JITCompiler::compileBody):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
(JSC::DFG::JITCompiler::jitAssertIsInt32):
(JSC::DFG::JITCompiler::jitAssertIsJSInt32):
(JSC::DFG::JITCompiler::jitAssertIsJSNumber):
(JSC::DFG::JITCompiler::jitAssertIsJSDouble):
(JSC::DFG::JITCompiler::jitAssertIsCell):
(JSC::DFG::JITCompiler::emitCount):
(JSC::DFG::JITCompiler::setSamplingFlag):
(JSC::DFG::JITCompiler::clearSamplingFlag):
* dfg/DFGJITCompilerInlineMethods.h: Added.
(JSC::DFG::JITCompiler::emitLoadTag):
(JSC::DFG::JITCompiler::emitLoadPayload):
(JSC::DFG::JITCompiler::emitLoad):
(JSC::DFG::JITCompiler::emitLoad2):
(JSC::DFG::JITCompiler::emitLoadDouble):
(JSC::DFG::JITCompiler::emitLoadInt32ToDouble):
(JSC::DFG::JITCompiler::emitStore):
(JSC::DFG::JITCompiler::emitStoreInt32):
(JSC::DFG::JITCompiler::emitStoreCell):
(JSC::DFG::JITCompiler::emitStoreBool):
(JSC::DFG::JITCompiler::emitStoreDouble):
* dfg/DFGNode.h:
* dfg/DFGOperations.cpp:
* dfg/DFGRepatch.cpp:
(JSC::DFG::generateProtoChainAccessStub):
(JSC::DFG::tryCacheGetByID):
(JSC::DFG::tryBuildGetByIDList):
(JSC::DFG::tryCachePutByID):
* dfg/DFGSpeculativeJIT.cpp:
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::ValueRecovery::inGPR):
(JSC::DFG::ValueRecovery::inPair):
(JSC::DFG::ValueRecovery::tagGPR):
(JSC::DFG::ValueRecovery::payloadGPR):
* dfg/DFGSpeculativeJIT32_64.cpp: Added.
(JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
(JSC::DFG::ValueSource::dump):
(JSC::DFG::ValueRecovery::dump):
(JSC::DFG::OSRExit::OSRExit):
(JSC::DFG::OSRExit::dump):
(JSC::DFG::SpeculativeJIT::fillSpeculateInt):
(JSC::DFG::SpeculativeJIT::fillSpeculateIntStrict):
(JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
(JSC::DFG::SpeculativeJIT::compilePeepHoleIntegerBranch):
(JSC::DFG::SpeculativeJIT::convertToDouble):
(JSC::DFG::SpeculativeJIT::compilePeepHoleDoubleBranch):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compare):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileMovHint):
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::initializeVariableTypes):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
* runtime/JSValue.h:
2011-09-23 Filip Pizlo <fpizlo@apple.com>
wtf/BitVector.h has a variety of bugs which manifest when the
......@@ -52,6 +52,7 @@ public:
using MacroAssemblerX86Common::call;
using MacroAssemblerX86Common::addDouble;
using MacroAssemblerX86Common::loadDouble;
using MacroAssemblerX86Common::storeDouble;
using MacroAssemblerX86Common::convertInt32ToDouble;
void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
......@@ -100,6 +101,12 @@ public:
m_assembler.movsd_mr(address, dest);
}
void storeDouble(FPRegisterID src, const void* address)
{
ASSERT(isSSE2Present());
m_assembler.movsd_rm(src, address);
}
void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
{
m_assembler.cvtsi2sd_mr(src.m_ptr, dest);
......
......@@ -1436,6 +1436,11 @@ public:
m_formatter.prefix(PRE_SSE_F2);
m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, address);
}
void movsd_rm(XMMRegisterID src, const void* address)
{
m_formatter.prefix(PRE_SSE_F2);
m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, address);
}
#endif
void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
......
......@@ -134,6 +134,9 @@ namespace JSC {
#if ENABLE(DFG_JIT)
int8_t baseGPR;
#if USE(JSVALUE32_64)
int8_t valueTagGPR;
#endif
int8_t valueGPR;
int8_t scratchGPR;
int16_t deltaCallToDone;
......
......@@ -1366,7 +1366,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_end:
addToGraph(Return, get(currentInstruction[1].u.operand));
LAST_OPCODE(op_end);
case op_throw:
addToGraph(Throw, get(currentInstruction[1].u.operand));
LAST_OPCODE(op_throw);
......@@ -1375,6 +1375,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
addToGraph(ThrowReferenceError);
LAST_OPCODE(op_throw_reference_error);
#if USE(JSVALUE64)
case op_call: {
NodeIndex callTarget = get(currentInstruction[1].u.operand);
if (m_graph.isFunctionConstant(m_codeBlock, callTarget)) {
......@@ -1408,6 +1409,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
addCall(interpreter, currentInstruction, Construct);
NEXT_OPCODE(op_construct);
}
#endif
case op_call_put_result:
NEXT_OPCODE(op_call_put_result);
......
......@@ -111,8 +111,10 @@ inline bool canCompileOpcode(OpcodeID opcodeID)
case op_loop_if_greatereq:
case op_ret:
case op_end:
#if USE(JSVALUE64)
case op_call:
case op_construct:
#endif
case op_call_put_result:
case op_resolve:
case op_resolve_base:
......
......@@ -76,6 +76,7 @@ public:
static const char* debugName(FPRReg reg)
{
ASSERT(reg != InvalidFPRReg);
#if CPU(X86_64)
ASSERT(reg < 16);
static const char* nameForRegister[16] = {
"xmm0", "xmm1", "xmm2", "xmm3",
......@@ -83,6 +84,13 @@ public:
"xmm8", "xmm9", "xmm10", "xmm11",
"xmm12", "xmm13", "xmm14", "xmm15"
};
#elif CPU(X86)
ASSERT(reg < 8);
static const char* nameForRegister[8] = {
"xmm0", "xmm1", "xmm2", "xmm3",
"xmm4", "xmm5", "xmm6", "xmm7"
};
#endif
return nameForRegister[reg];
}
#endif
......
......@@ -41,17 +41,18 @@ typedef MacroAssembler::RegisterID GPRReg;
class GPRInfo {
public:
typedef GPRReg RegisterType;
static const unsigned numberOfRegisters = 4;
static const unsigned numberOfRegisters = 5;
// These registers match the baseline JIT.
static const GPRReg cachedResultRegister = X86Registers::eax;
static const GPRReg timeoutCheckRegister = X86Registers::esi;
static const GPRReg cachedResultRegister2 = X86Registers::edx;
static const GPRReg callFrameRegister = X86Registers::edi;
// Temporary registers.
static const GPRReg regT0 = X86Registers::eax;
static const GPRReg regT1 = X86Registers::edx;
static const GPRReg regT2 = X86Registers::ecx;
static const GPRReg regT3 = X86Registers::ebx;
static const GPRReg regT4 = X86Registers::esi;
// These constants provide the names for the general purpose argument & return value registers.
static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2
static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
......@@ -61,7 +62,7 @@ public:
static GPRReg toRegister(unsigned index)
{
ASSERT(index < numberOfRegisters);
static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, };
static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4 };
return registerForIndex[index];
}
......@@ -69,7 +70,7 @@ public:
{
ASSERT(reg != InvalidGPRReg);
ASSERT(reg < 8);
static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, InvalidIndex };
unsigned result = indexForRegister[reg];
ASSERT(result != InvalidIndex);
return result;
......@@ -81,8 +82,8 @@ public:
ASSERT(reg != InvalidGPRReg);
ASSERT(reg < 8);
static const char* nameForRegister[8] = {
"rax", "rcx", "rdx", "rbx",
"rsp", "rbp", "rsi", "rdi",
"eax", "ecx", "edx", "ebx",
"esp", "ebp", "esi", "edi",
};
return nameForRegister[reg];
}
......
......@@ -84,6 +84,7 @@ inline const char* dataFormatToString(DataFormat dataFormat)
}
#endif
#if USE(JSVALUE64)
inline bool needDataFormatConversion(DataFormat from, DataFormat to)
{
ASSERT(from != DataFormatNone);
......@@ -123,6 +124,41 @@ inline bool needDataFormatConversion(DataFormat from, DataFormat to)
return true;
}
#elif USE(JSVALUE32_64)
inline bool needDataFormatConversion(DataFormat from, DataFormat to)
{
ASSERT(from != DataFormatNone);
ASSERT(to != DataFormatNone);
switch (from) {
case DataFormatInteger:
case DataFormatCell:
return to != DataFormatInteger && to != DataFormatCell;
case DataFormatDouble:
case DataFormatJSDouble:
switch (to) {
case DataFormatDouble:
case DataFormatJS:
case DataFormatJSDouble:
return false;
default:
return true;
}
case DataFormatJS:
return !(to & DataFormatJS);
case DataFormatJSInteger:
case DataFormatJSCell:
case DataFormatJSBoolean:
return to != DataFormatJS && to != from;
case DataFormatStorage:
ASSERT(to == DataFormatStorage);
return false;
default:
ASSERT_NOT_REACHED();
}
return true;
}
#endif
inline bool isJSFormat(DataFormat format, DataFormat expectedFormat)
{
ASSERT(expectedFormat & DataFormatJS);
......@@ -186,6 +222,7 @@ public:
m_canFill = false;
u.gpr = gpr;
}
#if USE(JSVALUE64)
void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS)
{
ASSERT(format & DataFormatJS);
......@@ -197,6 +234,20 @@ public:
m_canFill = false;
u.gpr = gpr;
}
#elif USE(JSVALUE32_64)
void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg tagGPR, GPRReg payloadGPR, DataFormat format = DataFormatJS)
{
ASSERT(format & DataFormatJS);
m_nodeIndex = nodeIndex;
m_useCount = useCount;
m_registerFormat = format;
m_spillFormat = DataFormatNone;
m_canFill = false;
u.v.tagGPR = tagGPR;
u.v.payloadGPR = payloadGPR;
}
#endif
void initCell(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
{
m_nodeIndex = nodeIndex;
......@@ -208,6 +259,7 @@ public:
}
void initDouble(NodeIndex nodeIndex, uint32_t useCount, FPRReg fpr)
{
ASSERT(fpr != InvalidFPRReg);
m_nodeIndex = nodeIndex;
m_useCount = useCount;
m_registerFormat = DataFormatDouble;
......@@ -282,8 +334,15 @@ public:
}
// Get the machine resister currently holding the value.
#if USE(JSVALUE64)
GPRReg gpr() { ASSERT(m_registerFormat && m_registerFormat != DataFormatDouble); return u.gpr; }
FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble); return u.fpr; }
#elif USE(JSVALUE32_64)
GPRReg gpr() { ASSERT(m_registerFormat == DataFormatInteger || m_registerFormat == DataFormatCell || m_registerFormat == DataFormatStorage); return u.gpr; }
GPRReg tagGPR() { ASSERT(m_registerFormat & DataFormatJS); return u.v.tagGPR; }
GPRReg payloadGPR() { ASSERT(m_registerFormat & DataFormatJS); return u.v.payloadGPR; }
FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble || m_registerFormat == DataFormatJSDouble); return u.fpr; }
#endif
// Check whether a value needs spilling in order to free up any associated machine registers.
bool needsSpill()
......@@ -332,12 +391,27 @@ public:
// Record that this value is filled into machine registers,
// tracking which registers, and what format the value has.
#if USE(JSVALUE64)
void fillJSValue(GPRReg gpr, DataFormat format = DataFormatJS)
{
ASSERT(format & DataFormatJS);
m_registerFormat = format;
u.gpr = gpr;
}
#elif USE(JSVALUE32_64)
void fillJSValue(GPRReg tagGPR, GPRReg payloadGPR, DataFormat format = DataFormatJS)
{
ASSERT(format & DataFormatJS);
m_registerFormat = format;
u.v.tagGPR = tagGPR; // FIXME: for JSValues with known type (boolean, integer, cell etc.) no tagGPR is needed?
u.v.payloadGPR = payloadGPR;
}
void fillCell(GPRReg gpr)
{
m_registerFormat = DataFormatCell;
u.gpr = gpr;
}
#endif
void fillInteger(GPRReg gpr)
{
m_registerFormat = DataFormatInteger;
......@@ -345,6 +419,7 @@ public:
}
void fillDouble(FPRReg fpr)
{
ASSERT(fpr != InvalidFPRReg);
m_registerFormat = DataFormatDouble;
u.fpr = fpr;
}
......@@ -369,6 +444,12 @@ private:
union {
GPRReg gpr;
FPRReg fpr;
#if USE(JSVALUE32_64)
struct {
GPRReg tagGPR;
GPRReg payloadGPR;
} v;
#endif
} u;
};
......
......@@ -27,6 +27,7 @@
#include "DFGJITCodeGenerator.h"
#if ENABLE(DFG_JIT)
#if USE(JSVALUE64)
#include "DFGSpeculativeJIT.h"
#include "LinkBuffer.h"
......@@ -2269,3 +2270,4 @@ FPRTemporary::FPRTemporary(JITCodeGenerator* jit, SpeculateDoubleOperand& op1, S
} } // namespace JSC::DFG
#endif
#endif
This diff is collapsed.
......@@ -27,6 +27,7 @@
#include "DFGJITCompiler.h"
#if ENABLE(DFG_JIT)
#if USE(JSVALUE64)
#include "CodeBlock.h"
#include "DFGJITCodeGenerator.h"
......@@ -772,3 +773,4 @@ void JITCompiler::clearSamplingFlag(int32_t flag)
} } // namespace JSC::DFG
#endif
#endif
......@@ -134,7 +134,7 @@ public:
JSGlobalData* globalData() { return m_globalData; }
AssemblerType_T& assembler() { return m_assembler; }
#if CPU(X86_64)
#if CPU(X86_64) || CPU(X86)
void preserveReturnAddressAfterCall(GPRReg reg)
{
pop(reg);
......@@ -170,6 +170,16 @@ public:
return Address(global, varNumber * sizeof(Register));
}
static Address tagForGlobalVar(GPRReg global, int32_t varNumber)
{
return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
}
static Address payloadForGlobalVar(GPRReg global, int32_t varNumber)
{
return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
}
static Address addressFor(VirtualRegister virtualRegister)
{
return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register));
......@@ -207,7 +217,11 @@ public:
Call appendCallWithExceptionCheck(const FunctionPtr& function, CodeOrigin codeOrigin)
{
Call functionCall = call();
#if USE(JSVALUE64)
Jump exceptionCheck = branchTestPtr(NonZero, AbsoluteAddress(&globalData()->exception));
#elif USE(JSVALUE32_64)
Jump exceptionCheck = branch32(NotEqual, AbsoluteAddress(reinterpret_cast<char*>(&globalData()->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
#endif
m_calls.append(CallRecord(functionCall, function, exceptionCheck, codeOrigin));
return functionCall;
}
......@@ -259,6 +273,33 @@ public:
bool valueOfBooleanConstant(NodeIndex nodeIndex) { return graph().valueOfBooleanConstant(codeBlock(), nodeIndex); }
JSFunction* valueOfFunctionConstant(NodeIndex nodeIndex) { return graph().valueOfFunctionConstant(codeBlock(), nodeIndex); }
#if USE(JSVALUE32_64)
void* addressOfDoubleConstant(NodeIndex nodeIndex)
{
ASSERT(isNumberConstant(nodeIndex));
unsigned constantIndex = graph()[nodeIndex].constantNumber();
return &(codeBlock()->constantRegister(FirstConstantRegisterIndex + constantIndex));
}
void emitLoadTag(NodeIndex, GPRReg tag);
void emitLoadPayload(NodeIndex, GPRReg payload);
void emitLoad(const JSValue&, GPRReg tag, GPRReg payload);