WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
almost done
blah.patch (text/plain), 17.22 KB, created by
Filip Pizlo
on 2015-12-20 17:35:45 PST
(
hide
)
Description:
almost done
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2015-12-20 17:35:45 PST
Size:
17.22 KB
patch
obsolete
>Index: Source/JavaScriptCore/b3/B3ValueRep.cpp >=================================================================== >--- Source/JavaScriptCore/b3/B3ValueRep.cpp (revision 194320) >+++ Source/JavaScriptCore/b3/B3ValueRep.cpp (working copy) >@@ -28,6 +28,8 @@ > > #if ENABLE(B3_JIT) > >+#include "AssemblyHelpers.h" >+ > namespace JSC { namespace B3 { > > void ValueRep::dump(PrintStream& out) const >@@ -55,6 +57,49 @@ void ValueRep::dump(PrintStream& out) co > RELEASE_ASSERT_NOT_REACHED(); > } > >+void ValueRep::emitRestore(AssemblyHelpers& jit, Reg reg) >+{ >+ if (reg.isGPR()) { >+ switch (kind()) { >+ case Register: >+ if (isGPR()) >+ jit.move(gpr(), reg.gpr()); >+ else >+ jit.moveDoubleTo64(fpr(), reg.gpr()); >+ break; >+ case Stack: >+ jit.load64(AssemblyHelpers::Address(GPRInfo::callFrameRegister, offsetFromFP()), reg.gpr()); >+ break; >+ case Constant: >+ jit.move(TrustedImm64(value()), reg.gpr()); >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+ return; >+ } >+ >+ switch (kind()) { >+ case Register: >+ if (isGPR()) >+ jit.move64ToDouble(gpr(), reg.fpr()); >+ else >+ jit.moveDouble(fpr(), reg.fpr()); >+ break; >+ case Stack: >+ jit.loadDouble(AssemblyHelpers::Address(GPRInfo::callFrameRegister, offsetFromFP()), reg.fpr()); >+ break; >+ case Constant: >+ jit.move(TrustedImm64(value()), jit.scratchRegister()); >+ jit.move64ToDouble(jit.scratchRegister(), reg.fpr()); >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } >+} >+ > } } // namespace JSC::B3 > > namespace WTF { >Index: Source/JavaScriptCore/b3/B3ValueRep.h >=================================================================== >--- Source/JavaScriptCore/b3/B3ValueRep.h (revision 194320) >+++ Source/JavaScriptCore/b3/B3ValueRep.h (working copy) >@@ -34,7 +34,11 @@ > #include "Reg.h" > #include <wtf/PrintStream.h> > >-namespace JSC { namespace B3 { >+namespace JSC { >+ >+class AssemblyHelpers; >+ >+namespace B3 { > > // We use this class to describe value representations at stackmaps. It's used both to force a > // representation and to get the representation. When the B3 client forces a representation, we say >@@ -216,6 +220,10 @@ public: > > JS_EXPORT_PRIVATE void dump(PrintStream&) const; > >+ // This has a simple contract: it emits code to restore the value into the given register. This >+ // will work even if it requires moving between bits a GPR and a FPR. >+ void emitRestore(AssemblyHelpers&, Reg); >+ > private: > Kind m_kind; > union U { >Index: Source/JavaScriptCore/dfg/DFGCommon.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCommon.h (revision 194320) >+++ Source/JavaScriptCore/dfg/DFGCommon.h (working copy) >@@ -38,7 +38,7 @@ namespace JSC { namespace DFG { > // We are in the middle of an experimental transition from LLVM to B3 as the backend for the FTL. We don't > // yet know how it will turn out. For now, this flag will control whether FTL uses B3. Remember to set this > // to 0 before committing! >-#define FTL_USES_B3 0 >+#define FTL_USES_B3 1 > > struct Node; > >Index: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (revision 194320) >+++ Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (working copy) >@@ -205,8 +205,8 @@ public: > #endif // FTL_USE_B3 > > auto preOrder = m_graph.blocksInPreOrder(); >- >- // If we have any CallVarargs then we need to have a spill slot for it. >+ >+#if !FTL_USES_B3 > bool hasVarargs = false; > size_t maxNumberOfCatchSpills = 0; > for (DFG::BasicBlock* block : preOrder) { >@@ -270,10 +270,8 @@ public: > } > } > >-#if FTL_USES_B3 >- UNUSED_PARAM(hasVarargs); >- // FIXME >-#else >+ // B3 doesn't need the varargs spill slot because we just use call arg area size as a way to >+ // request spill slots. > if (hasVarargs) { > LValue varargsSpillSlots = m_out.alloca( > arrayType(m_out.int64, JSCallVarargs::numSpillSlotsNeeded())); >@@ -284,6 +282,7 @@ public: > m_out.int32Zero, varargsSpillSlots); > } > >+ // B3 doesn't need the exception spill slot because we just use the > if (m_graph.m_hasExceptionHandlers && maxNumberOfCatchSpills) { > RegisterSet volatileRegisters = RegisterSet::volatileRegistersForJSCall(); > maxNumberOfCatchSpills = std::min(volatileRegisters.numberOfSetRegisters(), maxNumberOfCatchSpills); >@@ -296,7 +295,7 @@ public: > m_out.constInt64(m_ftlState.exceptionHandlingSpillSlotStackmapID), > m_out.int32Zero, exceptionHandlingVolatileRegistersSpillSlots); > } >-#endif >+#endif // !FTL_USES_B3 > > // We should not create any alloca's after this point, since they will cease to > // be mem2reg candidates. >@@ -5069,32 +5068,216 @@ private: > > void compileCallOrConstructVarargs() > { >-#if FTL_USES_B3 >- if (verboseCompilationEnabled() || !verboseCompilationEnabled()) >- CRASH(); >-#else >+ Node* node = m_node; > LValue jsCallee = lowJSValue(m_node->child1()); > LValue thisArg = lowJSValue(m_node->child3()); > > LValue jsArguments = nullptr; >+ bool forwarding = false; > >- switch (m_node->op()) { >+ switch (node->op()) { > case CallVarargs: > case TailCallVarargs: > case TailCallVarargsInlinedCaller: > case ConstructVarargs: >- jsArguments = lowJSValue(m_node->child2()); >+ jsArguments = lowJSValue(node->child2()); > break; > case CallForwardVarargs: > case TailCallForwardVarargs: > case TailCallForwardVarargsInlinedCaller: > case ConstructForwardVarargs: >+ forwarding = true; > break; > default: >- DFG_CRASH(m_graph, m_node, "bad node type"); >+ DFG_CRASH(m_graph, node, "bad node type"); > break; > } > >+#if FTL_USES_B3 >+ // FIXME: Need a story for exceptions. >+ // https://bugs.webkit.org/show_bug.cgi?id=151686 >+ >+ PatckpointValue* patchpoint = m_out.patchpoint(Int64); >+ >+ // Append the forms of the arguments that we will use before any clobbering happens. >+ patchpoint->append(jsCallee, ValueRep::SomeRegister); >+ if (jsArguments) >+ patchpoint->append(jsArguments, ValueRep::SomeRegister); >+ patchpoint->append(thisArg, ValueRep::SomeRegister); >+ >+ if (!forwarding) { >+ // Now append them again for after clobbering. Note that the compiler may ask us to use a >+ // different register for the late for the post-clobbering version of the value. This gives >+ // the compiler to spill these values without having to burn any callee-saves. >+ patchpoint->append(jsCallee, ValueRep::LateColdAny); >+ patchpoint->append(jsArguments, ValueRep::LateColdAny); >+ patchpoint->append(thisArg, ValueRep::LateColdAny); >+ } >+ >+ patchpoint->clobber(RegisterSet::macroScratchRegisters()); >+ parchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall()); >+ patchpoint->resultConstraint = ValueRep::reg(GPRInfo::returnValueGPR); >+ >+ // This is the minimum amount of call arg area stack space that all JS->JS calls always have. >+ unsigned minimumJSCallAreaSize = >+ sizeof(CallerFrameAndPC) + >+ WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(EncodedJSValue)); >+ >+ m_proc.requestCallArgAreaSize(minimumJSCallAreaSize); >+ >+ CodeOrigin codeOrigin = codeOriginDescriptionOfCallSite(); >+ State* state = &m_ftlState; >+ patchpoint->setGenerator( >+ [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { >+ AllowMacroScratchRegisterUsage allowScratch(jit); >+ CallSiteIndex callSiteIndex = >+ state->jitCode->common.addUniqueCallSiteIndex(codeOrigin); >+ >+ // FIXME: We would ask the OSR exit descriptor to prepare and then we would modify >+ // the OSRExit data structure inside the OSRExitHandle to link it up to this call. >+ // Also, the exception checks JumpList should be linked to somewhere. >+ // https://bugs.webkit.org/show_bug.cgi?id=151686 >+ CCallHelpers::JumpList exceptions; >+ >+ jit.store32( >+ CCallHelpers::TrustedImm32(callSiteIndex.bits()), >+ CCallHelpers::tagFor(VirtualRegister(JSStack::ArgumentCount))); >+ >+ CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo(); >+ CallVarargsData* data = node->callVarargsData(); >+ >+ unsigned argIndex = 1; >+ GPRReg calleeGPR = params[argIndex++].gpr(); >+ GPRReg argumentsGPR = jsArguments ? params[argIndex++].gpr() : InvalidGPRReg; >+ GPRReg thisGPR = params[argIndex++].gpr(); >+ >+ B3::ValueRep calleeLateRep; >+ B3::ValueRep argumentsLateRep; >+ B3::ValueRep thisLateRep; >+ if (!forwarding) { >+ calleeLateRep = params[argIndex++]; >+ argumentsLateRep = params[argIndex++]; >+ thisLateRep = params[argIndex++]; >+ } >+ >+ // Get some scratch registers. >+ RegisterSet usedRegisters; >+ usedRegisters.merge(RegisterSet::stackRegisters()); >+ usedRegisters.merge(RegisterSet::reservedHardwareRegisters()); >+ usedRegisters.merge(RegisterSet::calleeSaveRegisters()); >+ usedRegisters.set(calleeGPR); >+ if (argumentsGPR != InvalidGPRReg) >+ usedRegisters.set(argumentsGPR); >+ usedRegisters.set(thisGPR); >+ if (calleeLateRep.isReg()) >+ usedRegisters.set(calleeLateRep.reg()); >+ if (argumentsLateRep.isReg()) >+ usedRegisters.set(argumentsLateRep.reg()); >+ if (thisLateRep.isReg()) >+ usedRegisters.set(thisLateRep.reg()); >+ ScratchRegisterAllocator allocator(usedRegisters); >+ GPRReg scratchGPR1 = allocator.allocateScratchGPR(); >+ GPRReg scratchGPR2 = allocator.allocateScratchGPR(); >+ GPRReg scratchGPR3 = forwarding ? allocator.allocateScratchGPR() : InvalidGPRReg; >+ RELEASE_ASSERT(!allocator.numberOfReusedRegisters()); >+ >+ auto callWithExceptionCheck = [&] (void* callee) { >+ jit.move(CCallHelpers::TrustedImmPtr(callee), GPRInfo::nonPreservedNonArgumentGPR); >+ jit.call(GPRInfo::nonPreservedNonArgumentGPR); >+ exceptions.append(jit.emitExceptionCheck(AssemblyHelpers::NormalExceptionCheck, AssemblyHelpers::FarJumpWidth)); >+ }; >+ >+ auto adjustStack = [&] (GPRReg amount) { >+ jit.addPtr(CCallHelpers::TrustedImm32(sizeof(CallerFrameAndPC)), amount, CCallHelpers::stackPointerRegister); >+ }; >+ >+ unsigned originalStackHeight = params.proc().frameSize(); >+ >+ if (forwarding) { >+ jit.move(TrustedImm32(originalStackHeight / sizeof(EncodedJSValue)), scratchGPR2); >+ >+ CCallHelpers::JumpList slowCase; >+ emitSetupVarargsFrameFastCase(jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, node->child2()->origin.semantic.inlineCallFrame, data->firstVarArgOffset, slowCase); >+ >+ CCallHelpers::Jump done = jit.jump(); >+ slowCase.link(&jit); >+ jit.setupArgumentsExecState(); >+ callWithExceptionCheck(bitwise_cast<void*>(operationThrowStackOverflowForVarargs)); >+ jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow); >+ >+ done.link(&jit); >+ >+ adjustStack(scratchGPR2); >+ jit.move(calleeGPR, GPRInfo::regT0); >+ } else { >+ jit.move(TrustedImm32(originalStackHeight / sizeof(EncodedJSValue)), scratchGPR1); >+ jit.setupArgumentsWithExecState(argumentsGPR, scratchGPR1, CCallHelpers::TrustedImm32(data->firstVarArgOffset)); >+ callWithExceptionCheck(bitwise_cast<void*>(operationSizeFrameForVarargs)); >+ >+ jit.move(GPRInfo::returnValueGPR, scratchGPR1); >+ jit.move(CCallHelpers::TrustedImm32(originalStackHeight / sizeof(EncodedJSValue)), scratchGPR2); >+ argumentsLateRep.emitRestore(jit, argumentsGPR); >+ emitSetVarargsFrame(jit, scratchGPR1, false, scratchGPR2, scratchGPR2); >+ jit.addPtr(CCallHelpers::TrustedImm32(-minimumJSCallAreaSize), scratchGPR2, CCallHelpers::stackPointerRegister); >+ jit.setupArgumentsWithExecState(scratchGPR2, argumentsGPR, CCallHelpers::TrustedImm32(data->firstVarArgOffset), scratchGPR1); >+ callWithExceptionCheck(bitwise_cast<void*>(operationSetupVarargsFrame)); >+ >+ adjustStack(GPRInfo::returnValueGPR); >+ >+ // Now we need to dump thisLateRep into the stack and we need to put the callee >+ // into regT0. Note that neither of the LateRep's can use volatile registers, so >+ // taking care of callee first is wise. >+ calleeLateRep.emitRestore(jit, GPRInfo::regT0); >+ >+ thisLateRep.emitRestore(jit, thisGPR); // This may not emit code if thisGPR got a callee-save. >+ jit.store64(GPRInfo::regT0, CCallHelpers::calleeFrameSlot(JSStack::Callee)); >+ jit.store64(thisGPR, CCallHelpers::calleeArgumentSlot(0)); >+ >+ CallLinkInfo* callLinkInfo = jit.codeBlock()->addCallLinkInfo(); >+ >+ CCallHelpers::DateLabelPtr targetToCheck; >+ CCallHelpers::Jump slowPath = jit.branchPtrWithPatch( >+ CCallHelpers::NotEqual, GPRInfo::regT0, targetToCheck, >+ CCallHelpers::TrustedImmPtr(0)); >+ >+ CCallHelpers::Jump fastCall = jit.nearCall(); >+ CCallHelpers::Jump done = jit.jump(); >+ >+ slowPath.link(&jit); >+ >+ jit.move(CCallHelpers::TrustedImmPtr(callLinkInfo, GPRInfo::regT2)); >+ CCallHelpers::Call slowCall = jit.nearCall(); >+ done.link(&jit); >+ >+ CallLinkInfo::CallType callType; >+ if (node->op() == ConstructVarargs || node->op() == ConstructForwardVarargs) >+ callType = CallLinkInfo::ConstructVarargs; >+ else if (node->op() == TailCallVarargs || node->op() == TailCallForwardVarargs) >+ callType = CallLinkInfo::TailCallVarargs; >+ else >+ callType = CallLinkInfo::CallVarargs; >+ callLinkInfo->setUpCall(callType, node->origin.semantic, GPRInfo::regT0); >+ >+ jit.addPtr( >+ CCallHelpers::TrustedImm32(-originalStackHeight), >+ GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister); >+ >+ jit.addLinkTask( >+ [=] (LinkBuffer& linkBuffer) { >+ MacroAssemblerCodePtr linkCall = >+ linkBuffer.vm().getCTIStub(linkCallThunkGenerator).code(); >+ linkBuffer.link(slowCall, FunctionPtr(linkCall.executableAddress())); >+ >+ callLinkInfo->setCallLocations( >+ linkBuffer.locationOfNearCall(slowCall), >+ linkBuffer.locationOf(targetToCheck), >+ linkBuffer.locationOfNearCall(fastCall)); >+ }); >+ } >+ }); >+ >+ setJSValue(patchpoint); >+#else > unsigned stackmapID = m_stackmapIDs++; > > StackmapArgumentList arguments; >@@ -5108,15 +5291,15 @@ private: > > arguments.insert(0, m_out.constInt32(2 + !!jsArguments)); > arguments.insert(0, constNull(m_out.ref8)); >- arguments.insert(0, m_out.constInt32(sizeOfICFor(m_node))); >+ arguments.insert(0, m_out.constInt32(sizeOfICFor(node))); > arguments.insert(0, m_out.constInt64(stackmapID)); > > LValue call = m_out.call(m_out.int64, m_out.patchpointInt64Intrinsic(), arguments); > setInstructionCallingConvention(call, LLVMCCallConv); > >- m_ftlState.jsCallVarargses.append(JSCallVarargs(stackmapID, m_node, codeOriginDescriptionOfCallSite())); >+ m_ftlState.jsCallVarargses.append(JSCallVarargs(stackmapID, node, codeOriginDescriptionOfCallSite())); > >- switch (m_node->op()) { >+ switch (node->op()) { > case TailCallVarargs: > case TailCallForwardVarargs: > m_out.unreachable();
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 152468
:
267723
|
267727
|
267728
|
267737
|
267754