]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - bytecode/CallLinkInfo.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / bytecode / CallLinkInfo.cpp
index 5b2661f06c75fc08f22cd756e2ae3f95c7a9eda0..d92009874a93857772c4366f4d009b546a33b9ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013, 2014 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 "DFGOperations.h"
 #include "DFGThunks.h"
+#include "JSCInlines.h"
+#include "Repatch.h"
 #include "RepatchBuffer.h"
+#include <wtf/ListDump.h>
+#include <wtf/NeverDestroyed.h>
 
 #if ENABLE(JIT)
 namespace JSC {
 
-void CallLinkInfo::unlink(VM& vm, RepatchBuffer& repatchBuffer)
+void CallLinkInfo::clearStub()
 {
-    ASSERT(isLinked());
+    if (!stub())
+        return;
+
+    m_stub->clearCallNodesFor(this);
+    m_stub = nullptr;
+}
+
+void CallLinkInfo::unlink(RepatchBuffer& repatchBuffer)
+{
+    if (!isLinked()) {
+        // We could be called even if we're not linked anymore because of how polymorphic calls
+        // work. Each callsite within the polymorphic call stub may separately ask us to unlink().
+        RELEASE_ASSERT(!isOnList());
+        return;
+    }
     
-    repatchBuffer.revertJumpReplacementToBranchPtrWithPatch(RepatchBuffer::startOfBranchPtrWithPatchOnRegister(hotPathBegin), static_cast<MacroAssembler::RegisterID>(calleeGPR), 0);
-    if (isDFG) {
-#if ENABLE(DFG_JIT)
-        repatchBuffer.relink(callReturnLocation, (callType == Construct ? vm.getCTIStub(DFG::linkConstructThunkGenerator) : vm.getCTIStub(DFG::linkCallThunkGenerator)).code());
-#else
-        RELEASE_ASSERT_NOT_REACHED();
-#endif
-    } else
-        repatchBuffer.relink(callReturnLocation, callType == Construct ? vm.getCTIStub(linkConstructGenerator).code() : vm.getCTIStub(linkCallGenerator).code());
-    hasSeenShouldRepatch = false;
-    callee.clear();
-    stub.clear();
+    unlinkFor(
+        repatchBuffer, *this,
+        (m_callType == Construct || m_callType == ConstructVarargs)? CodeForConstruct : CodeForCall,
+        m_isFTL ? MustPreserveRegisters : RegisterPreservationNotRequired);
 
     // It will be on a list if the callee has a code block.
     if (isOnList())
         remove();
 }
 
+void CallLinkInfo::visitWeak(RepatchBuffer& repatchBuffer)
+{
+    auto handleSpecificCallee = [&] (JSFunction* callee) {
+        if (Heap::isMarked(callee->executable()))
+            m_hasSeenClosure = true;
+        else
+            m_clearedByGC = true;
+    };
+    
+    if (isLinked()) {
+        if (stub()) {
+            if (!stub()->visitWeak(repatchBuffer)) {
+                if (Options::verboseOSR()) {
+                    dataLog(
+                        "Clearing closure call from ", *repatchBuffer.codeBlock(), " to ",
+                        listDump(stub()->variants()), ", stub routine ", RawPointer(stub()),
+                        ".\n");
+                }
+                unlink(repatchBuffer);
+                m_clearedByGC = true;
+            }
+        } else if (!Heap::isMarked(m_callee.get())) {
+            if (Options::verboseOSR()) {
+                dataLog(
+                    "Clearing call from ", *repatchBuffer.codeBlock(), " to ",
+                    RawPointer(m_callee.get()), " (",
+                    m_callee.get()->executable()->hashFor(specializationKind()),
+                    ").\n");
+            }
+            handleSpecificCallee(m_callee.get());
+            unlink(repatchBuffer);
+        }
+    }
+    if (haveLastSeenCallee() && !Heap::isMarked(lastSeenCallee())) {
+        handleSpecificCallee(lastSeenCallee());
+        clearLastSeenCallee();
+    }
+}
+
+CallLinkInfo& CallLinkInfo::dummy()
+{
+    static NeverDestroyed<CallLinkInfo> dummy;
+    return dummy;
+}
+
 } // namespace JSC
 #endif // ENABLE(JIT)