/ runtime / TestRunnerUtils.cpp
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