+ linkSlowFor(repatchBuffer, vm, callLinkInfo, CodeForConstruct);
+}
+
+void dfgLinkSlowFor(ExecState* exec, CallLinkInfo& callLinkInfo, CodeSpecializationKind kind)
+{
+ CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
+ VM* vm = callerCodeBlock->vm();
+
+ RepatchBuffer repatchBuffer(callerCodeBlock);
+
+ linkSlowFor(repatchBuffer, vm, callLinkInfo, kind);
+}
+
+void dfgLinkClosureCall(ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock, Structure* structure, ExecutableBase* executable, MacroAssemblerCodePtr codePtr)
+{
+ ASSERT(!callLinkInfo.stub);
+
+ CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
+ VM* vm = callerCodeBlock->vm();
+
+ GPRReg calleeGPR = static_cast<GPRReg>(callLinkInfo.calleeGPR);
+
+ CCallHelpers stubJit(vm, callerCodeBlock);
+
+ CCallHelpers::JumpList slowPath;
+
+#if USE(JSVALUE64)
+ slowPath.append(
+ stubJit.branchTest64(
+ CCallHelpers::NonZero, calleeGPR, GPRInfo::tagMaskRegister));
+#else
+ // We would have already checked that the callee is a cell.
+#endif
+
+ slowPath.append(
+ stubJit.branchPtr(
+ CCallHelpers::NotEqual,
+ CCallHelpers::Address(calleeGPR, JSCell::structureOffset()),
+ CCallHelpers::TrustedImmPtr(structure)));
+
+ slowPath.append(
+ stubJit.branchPtr(
+ CCallHelpers::NotEqual,
+ CCallHelpers::Address(calleeGPR, JSFunction::offsetOfExecutable()),
+ CCallHelpers::TrustedImmPtr(executable)));
+
+ stubJit.loadPtr(
+ CCallHelpers::Address(calleeGPR, JSFunction::offsetOfScopeChain()),
+ GPRInfo::returnValueGPR);
+
+#if USE(JSVALUE64)
+ stubJit.store64(
+ GPRInfo::returnValueGPR,
+ CCallHelpers::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register) * JSStack::ScopeChain)));
+#else
+ stubJit.storePtr(
+ GPRInfo::returnValueGPR,
+ CCallHelpers::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register) * JSStack::ScopeChain) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+ stubJit.store32(
+ CCallHelpers::TrustedImm32(JSValue::CellTag),
+ CCallHelpers::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register) * JSStack::ScopeChain) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+#endif
+
+ JITCompiler::Call call = stubJit.nearCall();
+ JITCompiler::Jump done = stubJit.jump();
+
+ slowPath.link(&stubJit);
+ stubJit.move(calleeGPR, GPRInfo::nonArgGPR0);
+#if USE(JSVALUE32_64)
+ stubJit.move(CCallHelpers::TrustedImm32(JSValue::CellTag), GPRInfo::nonArgGPR1);
+#endif
+ stubJit.move(CCallHelpers::TrustedImmPtr(callLinkInfo.callReturnLocation.executableAddress()), GPRInfo::nonArgGPR2);
+ stubJit.restoreReturnAddressBeforeReturn(GPRInfo::nonArgGPR2);
+ JITCompiler::Jump slow = stubJit.jump();
+
+ LinkBuffer patchBuffer(*vm, &stubJit, callerCodeBlock);
+
+ patchBuffer.link(call, FunctionPtr(codePtr.executableAddress()));
+ patchBuffer.link(done, callLinkInfo.callReturnLocation.labelAtOffset(0));
+ patchBuffer.link(slow, CodeLocationLabel(vm->getCTIStub(virtualCallThunkGenerator).code()));
+
+ RefPtr<ClosureCallStubRoutine> stubRoutine = adoptRef(new ClosureCallStubRoutine(
+ FINALIZE_DFG_CODE(
+ patchBuffer,
+ ("DFG closure call stub for %s, return point %p, target %p (%s)",
+ toCString(*callerCodeBlock).data(), callLinkInfo.callReturnLocation.labelAtOffset(0).executableAddress(),
+ codePtr.executableAddress(), toCString(pointerDump(calleeCodeBlock)).data())),
+ *vm, callerCodeBlock->ownerExecutable(), structure, executable, callLinkInfo.codeOrigin));
+
+ RepatchBuffer repatchBuffer(callerCodeBlock);
+
+ repatchBuffer.replaceWithJump(
+ RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo.hotPathBegin),
+ CodeLocationLabel(stubRoutine->code().code()));
+ linkSlowFor(repatchBuffer, vm, callLinkInfo, CodeForCall);
+
+ callLinkInfo.stub = stubRoutine.release();
+
+ ASSERT(!calleeCodeBlock || calleeCodeBlock->isIncomingCallAlreadyLinked(&callLinkInfo));