/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "CallLinkInfo.h"
#include "DFGOperations.h"
+#include "DFGThunks.h"
+#include "JSCInlines.h"
#include "RepatchBuffer.h"
+#include <wtf/NeverDestroyed.h>
#if ENABLE(JIT)
namespace JSC {
-void CallLinkInfo::unlink(JSGlobalData& globalData, RepatchBuffer& repatchBuffer)
+void CallLinkInfo::unlink(RepatchBuffer& repatchBuffer)
{
ASSERT(isLinked());
- if (isDFG) {
-#if ENABLE(DFG_JIT)
- repatchBuffer.relink(CodeLocationCall(callReturnLocation), callType == Construct ? DFG::operationLinkConstruct : DFG::operationLinkCall);
-#else
- ASSERT_NOT_REACHED();
-#endif
- } else
- repatchBuffer.relink(CodeLocationNearCall(callReturnLocation), callType == Construct ? globalData.jitStubs->ctiVirtualConstructLink() : globalData.jitStubs->ctiVirtualCallLink());
+ if (Options::showDisassembly())
+ dataLog("Unlinking call from ", callReturnLocation, " to ", pointerDump(repatchBuffer.codeBlock()), "\n");
+
+ repatchBuffer.revertJumpReplacementToBranchPtrWithPatch(RepatchBuffer::startOfBranchPtrWithPatchOnRegister(hotPathBegin), static_cast<MacroAssembler::RegisterID>(calleeGPR), 0);
+ repatchBuffer.relink(
+ callReturnLocation,
+ repatchBuffer.codeBlock()->vm()->getCTIStub(linkThunkGeneratorFor(
+ (callType == Construct || callType == ConstructVarargs)? CodeForConstruct : CodeForCall,
+ isFTL ? MustPreserveRegisters : RegisterPreservationNotRequired)).code());
hasSeenShouldRepatch = false;
callee.clear();
+ stub.clear();
// It will be on a list if the callee has a code block.
if (isOnList())
remove();
}
+void CallLinkInfo::visitWeak(RepatchBuffer& repatchBuffer)
+{
+ if (isLinked()) {
+ if (stub) {
+ if (!Heap::isMarked(stub->structure())
+ || !Heap::isMarked(stub->executable())) {
+ if (Options::verboseOSR()) {
+ dataLog(
+ "Clearing closure call from ", *repatchBuffer.codeBlock(), " to ",
+ stub->executable()->hashFor(specializationKind()),
+ ", stub routine ", RawPointer(stub.get()), ".\n");
+ }
+ unlink(repatchBuffer);
+ }
+ } else if (!Heap::isMarked(callee.get())) {
+ if (Options::verboseOSR()) {
+ dataLog(
+ "Clearing call from ", *repatchBuffer.codeBlock(), " to ",
+ RawPointer(callee.get()), " (",
+ callee.get()->executable()->hashFor(specializationKind()),
+ ").\n");
+ }
+ unlink(repatchBuffer);
+ }
+ }
+ if (!!lastSeenCallee && !Heap::isMarked(lastSeenCallee.get()))
+ lastSeenCallee.clear();
+}
+
+CallLinkInfo& CallLinkInfo::dummy()
+{
+ static NeverDestroyed<CallLinkInfo> dummy;
+ return dummy;
+}
+
} // namespace JSC
#endif // ENABLE(JIT)