/ bytecode / LLIntCallLinkInfo.h
LLIntCallLinkInfo.h
 1  /*
 2   * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
 3   *
 4   * Redistribution and use in source and binary forms, with or without
 5   * modification, are permitted provided that the following conditions
 6   * are met:
 7   * 1. Redistributions of source code must retain the above copyright
 8   *    notice, this list of conditions and the following disclaimer.
 9   * 2. Redistributions in binary form must reproduce the above copyright
10   *    notice, this list of conditions and the following disclaimer in the
11   *    documentation and/or other materials provided with the distribution.
12   *
13   * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21   * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24   */
25  
26  #pragma once
27  
28  #include "JSCPtrTag.h"
29  #include "JSFunction.h"
30  #include "MacroAssemblerCodeRef.h"
31  #include <wtf/SentinelLinkedList.h>
32  
33  namespace JSC {
34  
35  struct Instruction;
36  
37  class LLIntCallLinkInfo : public PackedRawSentinelNode<LLIntCallLinkInfo> {
38  public:
39      friend class LLIntOffsetsExtractor;
40  
41      static constexpr uintptr_t unlinkedBit = 0x1;
42  
43      LLIntCallLinkInfo() = default;
44      
45      ~LLIntCallLinkInfo()
46      {
47          if (isOnList())
48              remove();
49      }
50      
51      bool isLinked() const { return !(m_calleeOrLastSeenCalleeWithLinkBit & unlinkedBit); }
52      
53  
54      void link(VM& vm, JSCell* owner, JSObject* callee, MacroAssemblerCodePtr<JSEntryPtrTag> codePtr)
55      {
56          if (isOnList())
57              remove();
58          m_calleeOrLastSeenCalleeWithLinkBit = bitwise_cast<uintptr_t>(callee);
59          vm.heap.writeBarrier(owner, callee);
60          m_machineCodeTarget = codePtr;
61      }
62  
63      void unlink()
64      {
65          // Make link invalidated. It works because LLInt tests the given callee with this pointer. But it is still valid as lastSeenCallee!
66          m_calleeOrLastSeenCalleeWithLinkBit |= unlinkedBit;
67          m_machineCodeTarget = MacroAssemblerCodePtr<JSEntryPtrTag>();
68          if (isOnList())
69              remove();
70      }
71  
72      JSObject* callee() const
73      {
74          if (!isLinked())
75              return nullptr;
76          return bitwise_cast<JSObject*>(m_calleeOrLastSeenCalleeWithLinkBit);
77      }
78  
79      JSObject* lastSeenCallee() const
80      {
81          return bitwise_cast<JSObject*>(m_calleeOrLastSeenCalleeWithLinkBit & ~unlinkedBit);
82      }
83  
84      void clearLastSeenCallee()
85      {
86          m_calleeOrLastSeenCalleeWithLinkBit = unlinkedBit;
87      }
88  
89      ArrayProfile m_arrayProfile;
90  
91  private:
92      uintptr_t m_calleeOrLastSeenCalleeWithLinkBit { unlinkedBit };
93      MacroAssemblerCodePtr<JSEntryPtrTag> m_machineCodeTarget;
94  };
95  
96  } // namespace JSC