TestRunnerUtils.cpp
1 /* 2 * Copyright (C) 2013-2019 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 "TestRunnerUtils.h" 28 29 #include "CodeBlock.h" 30 #include "FunctionCodeBlock.h" 31 #include "JSCInlines.h" 32 33 namespace JSC { 34 35 FunctionExecutable* getExecutableForFunction(JSValue theFunctionValue) 36 { 37 if (!theFunctionValue.isCell()) 38 return nullptr; 39 40 VM& vm = theFunctionValue.asCell()->vm(); 41 JSFunction* theFunction = jsDynamicCast<JSFunction*>(vm, theFunctionValue); 42 if (!theFunction) 43 return nullptr; 44 45 FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(vm, 46 theFunction->executable()); 47 return executable; 48 } 49 50 CodeBlock* getSomeBaselineCodeBlockForFunction(JSValue theFunctionValue) 51 { 52 FunctionExecutable* executable = getExecutableForFunction(theFunctionValue); 53 if (!executable) 54 return nullptr; 55 56 CodeBlock* baselineCodeBlock = executable->baselineCodeBlockFor(CodeForCall); 57 58 if (!baselineCodeBlock) 59 baselineCodeBlock = executable->baselineCodeBlockFor(CodeForConstruct); 60 61 return baselineCodeBlock; 62 } 63 64 JSValue numberOfDFGCompiles(JSValue theFunctionValue) 65 { 66 bool pretendToHaveManyCompiles = false; 67 #if ENABLE(DFG_JIT) 68 if (!Options::useJIT() || !Options::useBaselineJIT() || !Options::useDFGJIT()) 69 pretendToHaveManyCompiles = true; 70 #else 71 pretendToHaveManyCompiles = true; 72 #endif 73 74 if (CodeBlock* baselineCodeBlock = getSomeBaselineCodeBlockForFunction(theFunctionValue)) { 75 if (pretendToHaveManyCompiles) 76 return jsNumber(1000000.0); 77 return jsNumber(baselineCodeBlock->numberOfDFGCompiles()); 78 } 79 80 return jsNumber(0); 81 } 82 83 JSValue setNeverInline(JSValue theFunctionValue) 84 { 85 if (FunctionExecutable* executable = getExecutableForFunction(theFunctionValue)) 86 executable->setNeverInline(true); 87 88 return jsUndefined(); 89 } 90 91 JSValue setNeverOptimize(JSValue theFunctionValue) 92 { 93 if (FunctionExecutable* executable = getExecutableForFunction(theFunctionValue)) 94 executable->setNeverOptimize(true); 95 96 return jsUndefined(); 97 } 98 99 JSValue optimizeNextInvocation(JSValue theFunctionValue) 100 { 101 #if ENABLE(JIT) 102 if (CodeBlock* baselineCodeBlock = getSomeBaselineCodeBlockForFunction(theFunctionValue)) 103 baselineCodeBlock->optimizeNextInvocation(); 104 #endif 105 UNUSED_PARAM(theFunctionValue); 106 return jsUndefined(); 107 } 108 109 JSValue failNextNewCodeBlock(JSGlobalObject* globalObject) 110 { 111 globalObject->vm().setFailNextNewCodeBlock(); 112 113 return jsUndefined(); 114 } 115 116 JSValue numberOfDFGCompiles(JSGlobalObject*, CallFrame* callFrame) 117 { 118 if (callFrame->argumentCount() < 1) 119 return jsUndefined(); 120 return numberOfDFGCompiles(callFrame->uncheckedArgument(0)); 121 } 122 123 JSValue setNeverInline(JSGlobalObject*, CallFrame* callFrame) 124 { 125 if (callFrame->argumentCount() < 1) 126 return jsUndefined(); 127 return setNeverInline(callFrame->uncheckedArgument(0)); 128 } 129 130 JSValue setNeverOptimize(JSGlobalObject*, CallFrame* callFrame) 131 { 132 if (callFrame->argumentCount() < 1) 133 return jsUndefined(); 134 return setNeverOptimize(callFrame->uncheckedArgument(0)); 135 } 136 137 JSValue setCannotUseOSRExitFuzzing(JSGlobalObject*, CallFrame* callFrame) 138 { 139 if (callFrame->argumentCount() < 1) 140 return jsUndefined(); 141 142 JSValue theFunctionValue = callFrame->uncheckedArgument(0); 143 if (FunctionExecutable* executable = getExecutableForFunction(theFunctionValue)) 144 executable->setCanUseOSRExitFuzzing(false); 145 146 return jsUndefined(); 147 } 148 149 JSValue optimizeNextInvocation(JSGlobalObject*, CallFrame* callFrame) 150 { 151 if (callFrame->argumentCount() < 1) 152 return jsUndefined(); 153 return optimizeNextInvocation(callFrame->uncheckedArgument(0)); 154 } 155 156 // This is a hook called at the bitter end of some of our tests. 157 void finalizeStatsAtEndOfTesting() 158 { 159 } 160 161 } // namespace JSC 162