CallVariant.cpp
1 /* 2 * Copyright (C) 2014-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 #include "config.h" 27 #include "CallVariant.h" 28 29 #include "JSCInlines.h" 30 #include <wtf/ListDump.h> 31 32 namespace JSC { 33 34 bool CallVariant::finalize(VM& vm) 35 { 36 if (m_callee && !vm.heap.isMarked(m_callee)) 37 return false; 38 return true; 39 } 40 41 bool CallVariant::merge(const CallVariant& other) 42 { 43 if (*this == other) 44 return true; 45 if (executable() == other.executable()) { 46 *this = despecifiedClosure(); 47 return true; 48 } 49 return false; 50 } 51 52 void CallVariant::filter(VM& vm, JSValue value) 53 { 54 if (!*this) 55 return; 56 57 if (!isClosureCall()) { 58 if (nonExecutableCallee() != value) 59 *this = CallVariant(); 60 return; 61 } 62 63 if (JSFunction* function = jsDynamicCast<JSFunction*>(vm, value)) { 64 if (function->executable() == executable()) 65 *this = CallVariant(function); 66 else 67 *this = CallVariant(); 68 return; 69 } 70 71 *this = CallVariant(); 72 } 73 74 void CallVariant::dump(PrintStream& out) const 75 { 76 if (!*this) { 77 out.print("null"); 78 return; 79 } 80 81 if (InternalFunction* internalFunction = this->internalFunction()) { 82 out.print("InternalFunction: ", JSValue(internalFunction)); 83 return; 84 } 85 86 if (JSFunction* function = this->function()) { 87 out.print("(Function: ", JSValue(function), "; Executable: ", *executable(), ")"); 88 return; 89 } 90 91 if (ExecutableBase* executable = this->executable()) { 92 out.print("(Executable: ", *executable, ")"); 93 return; 94 } 95 96 out.print("Non-executable callee: ", *nonExecutableCallee()); 97 } 98 99 CallVariantList variantListWithVariant(const CallVariantList& list, CallVariant variantToAdd) 100 { 101 ASSERT(variantToAdd); 102 CallVariantList result; 103 for (CallVariant variant : list) { 104 ASSERT(variant); 105 if (!!variantToAdd) { 106 if (variant == variantToAdd) 107 variantToAdd = CallVariant(); 108 else if (variant.despecifiedClosure() == variantToAdd.despecifiedClosure()) { 109 variant = variant.despecifiedClosure(); 110 variantToAdd = CallVariant(); 111 } 112 } 113 result.append(variant); 114 } 115 if (!!variantToAdd) 116 result.append(variantToAdd); 117 118 if (ASSERT_ENABLED) { 119 for (unsigned i = 0; i < result.size(); ++i) { 120 for (unsigned j = i + 1; j < result.size(); ++j) { 121 if (result[i] != result[j]) 122 continue; 123 124 dataLog("variantListWithVariant(", listDump(list), ", ", variantToAdd, ") failed: got duplicates in result: ", listDump(result), "\n"); 125 RELEASE_ASSERT_NOT_REACHED(); 126 } 127 } 128 } 129 130 return result; 131 } 132 133 CallVariantList despecifiedVariantList(const CallVariantList& list) 134 { 135 CallVariantList result; 136 for (CallVariant variant : list) 137 result = variantListWithVariant(result, variant.despecifiedClosure()); 138 return result; 139 } 140 141 } // namespace JSC 142