/ runtime / ScriptExecutable.h
ScriptExecutable.h
  1  /*
  2   * Copyright (C) 2009-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  #pragma once
 27  
 28  #include "ExecutableBase.h"
 29  
 30  namespace JSC {
 31  
 32  class JSArray;
 33  class JSTemplateObjectDescriptor;
 34  class IsoCellSet;
 35  
 36  class ScriptExecutable : public ExecutableBase {
 37  public:
 38      typedef ExecutableBase Base;
 39      static constexpr unsigned StructureFlags = Base::StructureFlags;
 40  
 41      static void destroy(JSCell*);
 42  
 43      using TemplateObjectMap = HashMap<uint64_t, WriteBarrier<JSArray>, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>;
 44          
 45      CodeBlockHash hashFor(CodeSpecializationKind) const;
 46  
 47      const SourceCode& source() const { return m_source; }
 48      intptr_t sourceID() const { return m_source.providerID(); }
 49      const SourceOrigin& sourceOrigin() const { return m_source.provider()->sourceOrigin(); }
 50      // This is NOT the path that should be used for computing relative paths from a script. Use SourceOrigin's URL for that, the values may or may not be the same... This should only be used for `error.sourceURL` and stack traces.
 51      const String& sourceURL() const { return m_source.provider()->sourceURL(); }
 52      int firstLine() const { return m_source.firstLine().oneBasedInt(); }
 53      JS_EXPORT_PRIVATE int lastLine() const;
 54      unsigned startColumn() const { return m_source.startColumn().oneBasedInt(); }
 55      JS_EXPORT_PRIVATE unsigned endColumn() const;
 56  
 57      Optional<int> overrideLineNumber(VM&) const;
 58      unsigned typeProfilingStartOffset(VM&) const;
 59      unsigned typeProfilingEndOffset(VM&) const;
 60  
 61      bool usesEval() const { return m_features & EvalFeature; }
 62      bool usesArguments() const { return m_features & ArgumentsFeature; }
 63      bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
 64      DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); }
 65      EvalContextType evalContextType() const { return static_cast<EvalContextType>(m_evalContextType); }
 66      bool isInStrictContext() const { return m_features & StrictModeFeature; }
 67      bool usesNonSimpleParameterList() const { return m_features & NonSimpleParameterListFeature; }
 68  
 69      void setNeverInline(bool value) { m_neverInline = value; }
 70      void setNeverOptimize(bool value) { m_neverOptimize = value; }
 71      void setNeverFTLOptimize(bool value) { m_neverFTLOptimize = value; }
 72      void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; }
 73      void setCanUseOSRExitFuzzing(bool value) { m_canUseOSRExitFuzzing = value; }
 74      bool neverInline() const { return m_neverInline; }
 75      bool neverOptimize() const { return m_neverOptimize; }
 76      bool neverFTLOptimize() const { return m_neverFTLOptimize; }
 77      bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; }
 78      bool isInliningCandidate() const { return !neverInline(); }
 79      bool isOkToOptimize() const { return !neverOptimize(); }
 80      bool canUseOSRExitFuzzing() const { return m_canUseOSRExitFuzzing; }
 81      bool isInsideOrdinaryFunction() const { return m_isInsideOrdinaryFunction; }
 82      
 83      bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; }
 84  
 85      CodeFeatures features() const { return m_features; }
 86          
 87      DECLARE_EXPORT_INFO;
 88  
 89      void recordParse(CodeFeatures, bool hasCapturedVariables, int lastLine, unsigned endColumn);
 90      void installCode(CodeBlock*);
 91      void installCode(VM&, CodeBlock*, CodeType, CodeSpecializationKind);
 92      CodeBlock* newCodeBlockFor(CodeSpecializationKind, JSFunction*, JSScope*, Exception*&);
 93      CodeBlock* newReplacementCodeBlockFor(CodeSpecializationKind);
 94  
 95      void clearCode(IsoCellSet&);
 96  
 97      Intrinsic intrinsic() const
 98      {
 99          return m_intrinsic;
100      }
101  
102      bool hasJITCodeForCall() const
103      {
104          return m_jitCodeForCall;
105      }
106      bool hasJITCodeForConstruct() const
107      {
108          return m_jitCodeForConstruct;
109      }
110  
111      // This function has an interesting GC story. Callers of this function are asking us to create a CodeBlock
112      // that is not jettisoned before this function returns. Callers are essentially asking for a strong reference
113      // to the CodeBlock. Because the Executable may be allocating the CodeBlock, we require callers to pass in
114      // their CodeBlock*& reference because it's safe for CodeBlock to be jettisoned if Executable is the only thing
115      // to point to it. This forces callers to have a CodeBlock* in a register or on the stack that will be marked
116      // by conservative GC if a GC happens after we create the CodeBlock.
117      template <typename ExecutableType>
118      Exception* prepareForExecution(VM&, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*& resultCodeBlock);
119  
120      ScriptExecutable* topLevelExecutable();
121      JSArray* createTemplateObject(JSGlobalObject*, JSTemplateObjectDescriptor*);
122  
123  private:
124      friend class ExecutableBase;
125      Exception* prepareForExecutionImpl(VM&, JSFunction*, JSScope*, CodeSpecializationKind, CodeBlock*&);
126  
127      bool hasClearableCode(VM&) const;
128  
129      TemplateObjectMap& ensureTemplateObjectMap(VM&);
130  
131  protected:
132      ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType, Intrinsic);
133  
134      void finishCreation(VM& vm)
135      {
136          Base::finishCreation(vm);
137  
138  #if ENABLE(CODEBLOCK_SAMPLING)
139          if (SamplingTool* sampler = vm.interpreter->sampler())
140              sampler->notifyOfScope(vm, this);
141  #endif
142      }
143  
144      void recordParse(CodeFeatures features, bool hasCapturedVariables)
145      {
146          m_features = features;
147          m_hasCapturedVariables = hasCapturedVariables;
148      }
149  
150      static TemplateObjectMap& ensureTemplateObjectMapImpl(std::unique_ptr<TemplateObjectMap>& dest);
151  
152      SourceCode m_source;
153      Intrinsic m_intrinsic { NoIntrinsic };
154      bool m_didTryToEnterInLoop { false };
155      CodeFeatures m_features;
156      OptionSet<CodeGenerationMode> m_codeGenerationModeForGeneratorBody;
157      bool m_hasCapturedVariables : 1;
158      bool m_neverInline : 1;
159      bool m_neverOptimize : 1;
160      bool m_neverFTLOptimize : 1;
161      bool m_isArrowFunctionContext : 1;
162      bool m_canUseOSRExitFuzzing : 1;
163      bool m_codeForGeneratorBodyWasGenerated : 1;
164      bool m_isInsideOrdinaryFunction : 1;
165      unsigned m_derivedContextType : 2; // DerivedContextType
166      unsigned m_evalContextType : 2; // EvalContextType
167  };
168  
169  } // namespace JSC