| /* |
| * Copyright (C) 2009-2019 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #pragma once |
| |
| #include "ArityCheckMode.h" |
| #include "CallData.h" |
| #include "CodeBlockHash.h" |
| #include "CodeSpecializationKind.h" |
| #include "JITCode.h" |
| #include "JSGlobalObject.h" |
| #include "UnlinkedCodeBlock.h" |
| #include "UnlinkedFunctionExecutable.h" |
| |
| namespace JSC { |
| |
| class CodeBlock; |
| class EvalCodeBlock; |
| class FunctionCodeBlock; |
| class JSScope; |
| class JSWebAssemblyModule; |
| class LLIntOffsetsExtractor; |
| class ModuleProgramCodeBlock; |
| class ProgramCodeBlock; |
| |
| enum CompilationKind { FirstCompilation, OptimizingCompilation }; |
| |
| inline bool isCall(CodeSpecializationKind kind) |
| { |
| if (kind == CodeForCall) |
| return true; |
| ASSERT(kind == CodeForConstruct); |
| return false; |
| } |
| |
| class ExecutableBase : public JSCell { |
| friend class JIT; |
| friend class LLIntOffsetsExtractor; |
| friend MacroAssemblerCodeRef<JITThunkPtrTag> boundFunctionCallGenerator(VM*); |
| |
| protected: |
| ExecutableBase(VM& vm, Structure* structure) |
| : JSCell(vm, structure) |
| { |
| } |
| |
| void finishCreation(VM& vm) |
| { |
| Base::finishCreation(vm); |
| } |
| |
| public: |
| typedef JSCell Base; |
| static constexpr unsigned StructureFlags = Base::StructureFlags; |
| |
| static constexpr bool needsDestruction = true; |
| static void destroy(JSCell*); |
| |
| // Force subclasses to override this. |
| template<typename, SubspaceAccess> |
| static void subspaceFor(VM&) { } |
| |
| CodeBlockHash hashFor(CodeSpecializationKind) const; |
| |
| bool isEvalExecutable() const |
| { |
| return type() == EvalExecutableType; |
| } |
| bool isFunctionExecutable() const |
| { |
| return type() == FunctionExecutableType; |
| } |
| bool isProgramExecutable() const |
| { |
| return type() == ProgramExecutableType; |
| } |
| bool isModuleProgramExecutable() |
| { |
| return type() == ModuleProgramExecutableType; |
| } |
| bool isHostFunction() const |
| { |
| return type() == NativeExecutableType; |
| } |
| |
| static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); } |
| |
| DECLARE_EXPORT_INFO; |
| |
| public: |
| Ref<JITCode> generatedJITCodeForCall() const |
| { |
| ASSERT(m_jitCodeForCall); |
| return *m_jitCodeForCall; |
| } |
| |
| Ref<JITCode> generatedJITCodeForConstruct() const |
| { |
| ASSERT(m_jitCodeForConstruct); |
| return *m_jitCodeForConstruct; |
| } |
| |
| Ref<JITCode> generatedJITCodeFor(CodeSpecializationKind kind) const |
| { |
| if (kind == CodeForCall) |
| return generatedJITCodeForCall(); |
| ASSERT(kind == CodeForConstruct); |
| return generatedJITCodeForConstruct(); |
| } |
| |
| MacroAssemblerCodePtr<JSEntryPtrTag> entrypointFor(CodeSpecializationKind kind, ArityCheckMode arity) |
| { |
| // Check if we have a cached result. We only have it for arity check because we use the |
| // no-arity entrypoint in non-virtual calls, which will "cache" this value directly in |
| // machine code. |
| if (arity == MustCheckArity) { |
| switch (kind) { |
| case CodeForCall: |
| if (MacroAssemblerCodePtr<JSEntryPtrTag> result = m_jitCodeForCallWithArityCheck) |
| return result; |
| break; |
| case CodeForConstruct: |
| if (MacroAssemblerCodePtr<JSEntryPtrTag> result = m_jitCodeForConstructWithArityCheck) |
| return result; |
| break; |
| } |
| } |
| MacroAssemblerCodePtr<JSEntryPtrTag> result = generatedJITCodeFor(kind)->addressForCall(arity); |
| if (arity == MustCheckArity) { |
| // Cache the result; this is necessary for the JIT's virtual call optimizations. |
| switch (kind) { |
| case CodeForCall: |
| m_jitCodeForCallWithArityCheck = result; |
| break; |
| case CodeForConstruct: |
| m_jitCodeForConstructWithArityCheck = result; |
| break; |
| } |
| } |
| return result; |
| } |
| |
| static ptrdiff_t offsetOfJITCodeWithArityCheckFor( |
| CodeSpecializationKind kind) |
| { |
| switch (kind) { |
| case CodeForCall: |
| return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForCallWithArityCheck); |
| case CodeForConstruct: |
| return OBJECT_OFFSETOF(ExecutableBase, m_jitCodeForConstructWithArityCheck); |
| } |
| RELEASE_ASSERT_NOT_REACHED(); |
| return 0; |
| } |
| |
| bool hasJITCodeForCall() const; |
| bool hasJITCodeForConstruct() const; |
| |
| bool hasJITCodeFor(CodeSpecializationKind kind) const |
| { |
| if (kind == CodeForCall) |
| return hasJITCodeForCall(); |
| ASSERT(kind == CodeForConstruct); |
| return hasJITCodeForConstruct(); |
| } |
| |
| // Intrinsics are only for calls, currently. |
| Intrinsic intrinsic() const; |
| |
| Intrinsic intrinsicFor(CodeSpecializationKind kind) const |
| { |
| if (isCall(kind)) |
| return intrinsic(); |
| return NoIntrinsic; |
| } |
| |
| void dump(PrintStream&) const; |
| |
| protected: |
| RefPtr<JITCode> m_jitCodeForCall; |
| RefPtr<JITCode> m_jitCodeForConstruct; |
| MacroAssemblerCodePtr<JSEntryPtrTag> m_jitCodeForCallWithArityCheck; |
| MacroAssemblerCodePtr<JSEntryPtrTag> m_jitCodeForConstructWithArityCheck; |
| }; |
| |
| } // namespace JSC |