11cb0ef41Sopenharmony_ci// Copyright 2009 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_EXECUTION_SIMULATOR_H_
61cb0ef41Sopenharmony_ci#define V8_EXECUTION_SIMULATOR_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/common/globals.h"
91cb0ef41Sopenharmony_ci#include "src/objects/code.h"
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci#if !defined(USE_SIMULATOR)
121cb0ef41Sopenharmony_ci#include "src/utils/utils.h"
131cb0ef41Sopenharmony_ci#endif
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
161cb0ef41Sopenharmony_ci// No simulator for ia32 or x64.
171cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_ARM64
181cb0ef41Sopenharmony_ci#include "src/execution/arm64/simulator-arm64.h"
191cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_ARM
201cb0ef41Sopenharmony_ci#include "src/execution/arm/simulator-arm.h"
211cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
221cb0ef41Sopenharmony_ci#include "src/execution/ppc/simulator-ppc.h"
231cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_MIPS
241cb0ef41Sopenharmony_ci#include "src/execution/mips/simulator-mips.h"
251cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_MIPS64
261cb0ef41Sopenharmony_ci#include "src/execution/mips64/simulator-mips64.h"
271cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_LOONG64
281cb0ef41Sopenharmony_ci#include "src/execution/loong64/simulator-loong64.h"
291cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_S390
301cb0ef41Sopenharmony_ci#include "src/execution/s390/simulator-s390.h"
311cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_RISCV64
321cb0ef41Sopenharmony_ci#include "src/execution/riscv64/simulator-riscv64.h"
331cb0ef41Sopenharmony_ci#else
341cb0ef41Sopenharmony_ci#error Unsupported target architecture.
351cb0ef41Sopenharmony_ci#endif
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_cinamespace v8 {
381cb0ef41Sopenharmony_cinamespace internal {
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci#if defined(USE_SIMULATOR)
411cb0ef41Sopenharmony_ci// Running with a simulator.
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci// The simulator has its own stack. Thus it has a different stack limit from
441cb0ef41Sopenharmony_ci// the C-based native code.  The JS-based limit normally points near the end of
451cb0ef41Sopenharmony_ci// the simulator stack.  When the C-based limit is exhausted we reflect that by
461cb0ef41Sopenharmony_ci// lowering the JS-based limit as well, to make stack checks trigger.
471cb0ef41Sopenharmony_ciclass SimulatorStack : public v8::internal::AllStatic {
481cb0ef41Sopenharmony_ci public:
491cb0ef41Sopenharmony_ci  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
501cb0ef41Sopenharmony_ci                                            uintptr_t c_limit) {
511cb0ef41Sopenharmony_ci    return Simulator::current(isolate)->StackLimit(c_limit);
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  // Returns the current stack address on the simulator stack frame.
551cb0ef41Sopenharmony_ci  // The returned address is comparable with JS stack address.
561cb0ef41Sopenharmony_ci  static inline uintptr_t RegisterJSStackComparableAddress(
571cb0ef41Sopenharmony_ci      v8::internal::Isolate* isolate) {
581cb0ef41Sopenharmony_ci    // The value of |kPlaceHolder| is actually not used.  It just occupies a
591cb0ef41Sopenharmony_ci    // single word on the stack frame of the simulator.
601cb0ef41Sopenharmony_ci    const uintptr_t kPlaceHolder = 0x4A535350u;  // "JSSP" in ASCII
611cb0ef41Sopenharmony_ci    return Simulator::current(isolate)->PushAddress(kPlaceHolder);
621cb0ef41Sopenharmony_ci  }
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  static inline void UnregisterJSStackComparableAddress(
651cb0ef41Sopenharmony_ci      v8::internal::Isolate* isolate) {
661cb0ef41Sopenharmony_ci    Simulator::current(isolate)->PopAddress();
671cb0ef41Sopenharmony_ci  }
681cb0ef41Sopenharmony_ci};
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci#else  // defined(USE_SIMULATOR)
711cb0ef41Sopenharmony_ci// Running without a simulator on a native platform.
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci// The stack limit beyond which we will throw stack overflow errors in
741cb0ef41Sopenharmony_ci// generated code. Because generated code uses the C stack, we just use
751cb0ef41Sopenharmony_ci// the C stack limit.
761cb0ef41Sopenharmony_ciclass SimulatorStack : public v8::internal::AllStatic {
771cb0ef41Sopenharmony_ci public:
781cb0ef41Sopenharmony_ci  static inline uintptr_t JsLimitFromCLimit(v8::internal::Isolate* isolate,
791cb0ef41Sopenharmony_ci                                            uintptr_t c_limit) {
801cb0ef41Sopenharmony_ci    USE(isolate);
811cb0ef41Sopenharmony_ci    return c_limit;
821cb0ef41Sopenharmony_ci  }
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci  // Returns the current stack address on the native stack frame.
851cb0ef41Sopenharmony_ci  // The returned address is comparable with JS stack address.
861cb0ef41Sopenharmony_ci  static inline uintptr_t RegisterJSStackComparableAddress(
871cb0ef41Sopenharmony_ci      v8::internal::Isolate* isolate) {
881cb0ef41Sopenharmony_ci    USE(isolate);
891cb0ef41Sopenharmony_ci    return internal::GetCurrentStackPosition();
901cb0ef41Sopenharmony_ci  }
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  static inline void UnregisterJSStackComparableAddress(
931cb0ef41Sopenharmony_ci      v8::internal::Isolate* isolate) {
941cb0ef41Sopenharmony_ci    USE(isolate);
951cb0ef41Sopenharmony_ci  }
961cb0ef41Sopenharmony_ci};
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci#endif  // defined(USE_SIMULATOR)
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci// Use this class either as {GeneratedCode<ret, arg1, arg2>} or
1011cb0ef41Sopenharmony_ci// {GeneratedCode<ret(arg1, arg2)>} (see specialization below).
1021cb0ef41Sopenharmony_citemplate <typename Return, typename... Args>
1031cb0ef41Sopenharmony_ciclass GeneratedCode {
1041cb0ef41Sopenharmony_ci public:
1051cb0ef41Sopenharmony_ci  using Signature = Return(Args...);
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  static GeneratedCode FromAddress(Isolate* isolate, Address addr) {
1081cb0ef41Sopenharmony_ci    return GeneratedCode(isolate, reinterpret_cast<Signature*>(addr));
1091cb0ef41Sopenharmony_ci  }
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  static GeneratedCode FromBuffer(Isolate* isolate, byte* buffer) {
1121cb0ef41Sopenharmony_ci    return GeneratedCode(isolate, reinterpret_cast<Signature*>(buffer));
1131cb0ef41Sopenharmony_ci  }
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  static GeneratedCode FromCode(Code code) {
1161cb0ef41Sopenharmony_ci    return FromAddress(code.GetIsolate(), code.entry());
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci#ifdef USE_SIMULATOR
1201cb0ef41Sopenharmony_ci  // Defined in simulator-base.h.
1211cb0ef41Sopenharmony_ci  Return Call(Args... args) {
1221cb0ef41Sopenharmony_ci// Starboard is a platform abstraction interface that also include Windows
1231cb0ef41Sopenharmony_ci// platforms like UWP.
1241cb0ef41Sopenharmony_ci#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN) && \
1251cb0ef41Sopenharmony_ci    !defined(V8_OS_STARBOARD) && !defined(V8_TARGET_ARCH_ARM)
1261cb0ef41Sopenharmony_ci    FATAL(
1271cb0ef41Sopenharmony_ci        "Generated code execution not possible during cross-compilation."
1281cb0ef41Sopenharmony_ci        "Also, generic C function calls are not implemented on 32-bit arm "
1291cb0ef41Sopenharmony_ci        "yet.");
1301cb0ef41Sopenharmony_ci#endif  // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN) &&
1311cb0ef41Sopenharmony_ci        // !defined(V8_OS_STARBOARD) && !defined(V8_TARGET_ARCH_ARM)
1321cb0ef41Sopenharmony_ci    return Simulator::current(isolate_)->template Call<Return>(
1331cb0ef41Sopenharmony_ci        reinterpret_cast<Address>(fn_ptr_), args...);
1341cb0ef41Sopenharmony_ci  }
1351cb0ef41Sopenharmony_ci#else
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  DISABLE_CFI_ICALL Return Call(Args... args) {
1381cb0ef41Sopenharmony_ci    // When running without a simulator we call the entry directly.
1391cb0ef41Sopenharmony_ci// Starboard is a platform abstraction interface that also include Windows
1401cb0ef41Sopenharmony_ci// platforms like UWP.
1411cb0ef41Sopenharmony_ci#if defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN) && \
1421cb0ef41Sopenharmony_ci    !defined(V8_OS_STARBOARD)
1431cb0ef41Sopenharmony_ci    FATAL("Generated code execution not possible during cross-compilation.");
1441cb0ef41Sopenharmony_ci#endif  // defined(V8_TARGET_OS_WIN) && !defined(V8_OS_WIN)
1451cb0ef41Sopenharmony_ci#if ABI_USES_FUNCTION_DESCRIPTORS
1461cb0ef41Sopenharmony_ci    // AIX ABI requires function descriptors (FD).  Artificially create a pseudo
1471cb0ef41Sopenharmony_ci    // FD to ensure correct dispatch to generated code.  The 'volatile'
1481cb0ef41Sopenharmony_ci    // declaration is required to avoid the compiler from not observing the
1491cb0ef41Sopenharmony_ci    // alias of the pseudo FD to the function pointer, and hence, optimizing the
1501cb0ef41Sopenharmony_ci    // pseudo FD declaration/initialization away.
1511cb0ef41Sopenharmony_ci    volatile Address function_desc[] = {reinterpret_cast<Address>(fn_ptr_), 0,
1521cb0ef41Sopenharmony_ci                                        0};
1531cb0ef41Sopenharmony_ci    Signature* fn = reinterpret_cast<Signature*>(function_desc);
1541cb0ef41Sopenharmony_ci    return fn(args...);
1551cb0ef41Sopenharmony_ci#else
1561cb0ef41Sopenharmony_ci    return fn_ptr_(args...);
1571cb0ef41Sopenharmony_ci#endif  // ABI_USES_FUNCTION_DESCRIPTORS
1581cb0ef41Sopenharmony_ci  }
1591cb0ef41Sopenharmony_ci#endif  // USE_SIMULATOR
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci private:
1621cb0ef41Sopenharmony_ci  friend class GeneratedCode<Return(Args...)>;
1631cb0ef41Sopenharmony_ci  Isolate* isolate_;
1641cb0ef41Sopenharmony_ci  Signature* fn_ptr_;
1651cb0ef41Sopenharmony_ci  GeneratedCode(Isolate* isolate, Signature* fn_ptr)
1661cb0ef41Sopenharmony_ci      : isolate_(isolate), fn_ptr_(fn_ptr) {}
1671cb0ef41Sopenharmony_ci};
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci// Allow to use {GeneratedCode<ret(arg1, arg2)>} instead of
1701cb0ef41Sopenharmony_ci// {GeneratedCode<ret, arg1, arg2>}.
1711cb0ef41Sopenharmony_citemplate <typename Return, typename... Args>
1721cb0ef41Sopenharmony_ciclass GeneratedCode<Return(Args...)> : public GeneratedCode<Return, Args...> {
1731cb0ef41Sopenharmony_ci public:
1741cb0ef41Sopenharmony_ci  // Automatically convert from {GeneratedCode<ret, arg1, arg2>} to
1751cb0ef41Sopenharmony_ci  // {GeneratedCode<ret(arg1, arg2)>}.
1761cb0ef41Sopenharmony_ci  GeneratedCode(GeneratedCode<Return, Args...> other)
1771cb0ef41Sopenharmony_ci      : GeneratedCode<Return, Args...>(other.isolate_, other.fn_ptr_) {}
1781cb0ef41Sopenharmony_ci};
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci}  // namespace internal
1811cb0ef41Sopenharmony_ci}  // namespace v8
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci#endif  // V8_EXECUTION_SIMULATOR_H_
184