/ bytecode / AccessCaseSnippetParams.cpp
AccessCaseSnippetParams.cpp
  1  /*
  2   * Copyright (C) 2016-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 "AccessCaseSnippetParams.h"
 28  
 29  #include "LinkBuffer.h"
 30  #include "PolymorphicAccess.h"
 31  #include "StructureStubInfo.h"
 32  
 33  #if ENABLE(JIT)
 34  
 35  namespace JSC {
 36  
 37  template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments>
 38  class SlowPathCallGeneratorWithArguments final : public AccessCaseSnippetParams::SlowPathCallGenerator {
 39  public:
 40      SlowPathCallGeneratorWithArguments(JumpType from, CCallHelpers::Label to, FunctionType function, ResultType result, std::tuple<Arguments...> arguments)
 41          : m_from(from)
 42          , m_to(to)
 43          , m_function(function)
 44          , m_result(result)
 45          , m_arguments(arguments)
 46      {
 47      }
 48  
 49      template<size_t... ArgumentsIndex>
 50      CCallHelpers::JumpList generateImpl(AccessGenerationState& state, const RegisterSet& usedRegistersBySnippet, CCallHelpers& jit, std::index_sequence<ArgumentsIndex...>)
 51      {
 52          CCallHelpers::JumpList exceptions;
 53          // We spill (1) the used registers by IC and (2) the used registers by Snippet.
 54          AccessGenerationState::SpillState spillState = state.preserveLiveRegistersToStackForCall(usedRegistersBySnippet);
 55  
 56          jit.store32(
 57              CCallHelpers::TrustedImm32(state.callSiteIndexForExceptionHandlingOrOriginal().bits()),
 58              CCallHelpers::tagFor(CallFrameSlot::argumentCountIncludingThis));
 59  
 60          jit.makeSpaceOnStackForCCall();
 61  
 62          jit.setupArguments<FunctionType>(std::get<ArgumentsIndex>(m_arguments)...);
 63          jit.prepareCallOperation(state.m_vm);
 64  
 65          CCallHelpers::Call operationCall = jit.call(OperationPtrTag);
 66          auto function = m_function;
 67          jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
 68              linkBuffer.link(operationCall, FunctionPtr<OperationPtrTag>(function));
 69          });
 70  
 71          jit.setupResults(m_result);
 72          jit.reclaimSpaceOnStackForCCall();
 73  
 74          CCallHelpers::Jump noException = jit.emitExceptionCheck(state.m_vm, CCallHelpers::InvertedExceptionCheck);
 75  
 76          state.restoreLiveRegistersFromStackForCallWithThrownException(spillState);
 77          exceptions.append(jit.jump());
 78  
 79          noException.link(&jit);
 80          RegisterSet dontRestore;
 81          dontRestore.set(m_result);
 82          state.restoreLiveRegistersFromStackForCall(spillState, dontRestore);
 83  
 84          return exceptions;
 85      }
 86  
 87      CCallHelpers::JumpList generate(AccessGenerationState& state, const RegisterSet& usedRegistersBySnippet, CCallHelpers& jit) final
 88      {
 89          m_from.link(&jit);
 90          CCallHelpers::JumpList exceptions = generateImpl(state, usedRegistersBySnippet, jit, std::make_index_sequence<std::tuple_size<std::tuple<Arguments...>>::value>());
 91          jit.jump().linkTo(m_to, &jit);
 92          return exceptions;
 93      }
 94  
 95  private:
 96      JumpType m_from;
 97      CCallHelpers::Label m_to;
 98      FunctionType m_function;
 99      ResultType m_result;
100      std::tuple<Arguments...> m_arguments;
101  };
102  
103  #define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) \
104      void AccessCaseSnippetParams::addSlowPathCallImpl(CCallHelpers::JumpList from, CCallHelpers& jit, OperationType operation, ResultType result, std::tuple<__VA_ARGS__> args) \
105      { \
106          CCallHelpers::Label to = jit.label(); \
107          m_generators.append(makeUnique<SlowPathCallGeneratorWithArguments<CCallHelpers::JumpList, OperationType, ResultType, __VA_ARGS__>>(from, to, operation, result, args)); \
108      } \
109  
110  SNIPPET_SLOW_PATH_CALLS(JSC_DEFINE_CALL_OPERATIONS)
111  #undef JSC_DEFINE_CALL_OPERATIONS
112  
113  CCallHelpers::JumpList AccessCaseSnippetParams::emitSlowPathCalls(AccessGenerationState& state, const RegisterSet& usedRegistersBySnippet, CCallHelpers& jit)
114  {
115      CCallHelpers::JumpList exceptions;
116      for (auto& generator : m_generators)
117          exceptions.append(generator->generate(state, usedRegistersBySnippet, jit));
118      return exceptions;
119  }
120  
121  }
122  
123  #endif