Changeset 294287 in webkit


Ignore:
Timestamp:
May 16, 2022, 10:21:53 PM (3 years ago)
Author:
mark.lam@apple.com
Message:

Add ARM64 disassembler support for symbolic dumping of some well known constants.
https://bugs.webkit.org/show_bug.cgi?id=240443

Reviewed by Yusuke Suzuki.

Source/JavaScriptCore:

  1. Added a Options::needDisassemblySupport() option. This option is true if any of the JSC disassembly options are enabled. This allows us to trivially check if we need to enable additional infrastructure (like those added in this patch) to support disassembly.
  1. Refactor the Disassembler's thunkLabelMap into a more generic labelMap. It can now map a pointer to a CString or a const char* label.
  1. Enable JITOperationList infrastructure when ENABLE(JIT_OPERATION_DISASSEMBLY) is true. This adds a name to the JITOperationAnnotation record. Since this is guarded by ENABLE(JIT_OPERATION_DISASSEMBLY), we can trivially turn this part off later if adding this name adds too much size burden (or if any unexpected issues arise). Turning this off will only disable disassembly of JIT operation names. Disassembly of other constants (see below) will still be supported.

If Options::needDisassemblySupport() is true, the JITOperationList will
register all JIT operations (and the LLInt ones as well) with the Disassembler
labelMap.

  1. Removed the < > brackets around branch target labels except for internal pc index labels (e.g. <716>) and <unknown> (when we don't know what the branch target is). The < > notation takes up space and doesn't add any info. The branch targets now look like this:

<32> 0x1180102c0: b.ne 0x1180101c0 -> thunk: native Tail With Saved Tags Call trampoline
<92> 0x11801c87c: b 0x118008980 -> thunk: LLInt function for call jump to prologue thunk

<3508> 0x1198e16b4: b 0x1198bc1a0 -> JIT PC

Internal pc index labels will still use the < > brackets:

<3476> 0x1198e1694: b.eq 0x1198e16a0 -> <3488>

  1. Added ARM64 disassembler support to compute the value of a constant being loaded into a register using "MoveWide" instructions e.g. movz and movk.

When the disassembler sees a movz or movn or mov (of the MoveWide variety),
the disassembler initializes a m_builtConstant value. With each subsequent
movk instruction with the same destination register, the disassembler splices
in the corresponding 16-bit immediate.

After disassembling a MoveWide instruction, it will check if the next
instruction is also a MoveWide instruction targeting the same destination
register. If so, the constant is still being build: hence, it does nothing and
continues.

If the next instruction is (a) a MoveWide instruction targeting a different
register, (b) not a MoveWide instruction, or (c) we've reached the end of the
LinkBuffer (i.e. there's no next instruction), then the constant building for
the current target register is complete.

  1. Added ARM64 disassembler support for looking up constants (built in (5) above) and printing symbolic info / names of those constants.

With ENABLE(JIT_OPERATION_DISASSEMBLY), we now have JIT operation names e.g.

<176> 0x118010270: movk x3, #0x9f6e, lsl #48 -> 0x102dc8950 operationVMHandleException
<164> 0x1180180a4: movk x8, #0xe5c, lsl #48 -> 0x102db9420 operationVirtualCall

Apart from looking up the constant in the Disassembler labelMap, it also looks
up some commonly used constants e.g.

  1. VM pointers:

<156> 0x11801105c: movk x0, #0x1, lsl #32 -> 0x139435000 vm

  1. Some VM internal pointers (more can be added later as needed):

<24> 0x118014d18: movk x17, #0x1, lsl #32 -> 0x13943ee78 vm +40568: vm.topCallFrame
<76> 0x118014d4c: movk x17, #0x1, lsl #32 -> 0x139441a10 vm +51728: vm.m_exception

<196> 0x118011244: movk x17, #0x1, lsl #32 -> 0x1394417d0 vm +51152: vm.targetMachinePCForThrow
<208> 0x1198e09d0: movk x17, #0x1, lsl #32 -> 0x104432cc0 vm +52416: vm.m_doesGC

  1. VM related pointers (only 1 for now; not VM fields, but hangs off of VM):

<12> 0x11801938c: movk x1, #0x1, lsl #32 -> 0x1052cd3c8 vm scratchBuffer.m_buffer

  1. Well known PtrTags:

<204> 0x11801124c: movz x16, #0x6f9b -> 0x6f9b ExceptionHandlerPtrTag ?
<212> 0x1180150d4: movz x16, #0x593 -> 0x593 JSEntryPtrTag ?
<168> 0x1180183a8: movz lr, #0xb389 -> 0xb389 OperationPtrTag ?

  • the ? is because we cannot be certain that the 16-bit constant is a PtrTag. It may just be a coincidence that the value is the same. However, the user can trivially look at the surrounding disassembled code, and be able to tell if the value is used as a PtrTag.

For constants that are not found in the known sets:

  1. Small 16-bit constant (prints decimal value for convenience):

<200> 0x1198e09c8: movz x17, #0x2cc0 -> 11456

  1. Unknown pointers that aren't in the JIT and LLINT regions will simply print the pointer / constant:

<88> 0x1198e0958: movz x17, #0x2088
<92> 0x1198e095c: movk x17, #0x30d, lsl #16
<96> 0x1198e0960: movk x17, #0x1, lsl #32 -> 0x1030d2088

<unknown> is only used in relative branches.

  1. Enhanced the Integrity::isSanePointer() check to reject pointer values that are less than 4G on CPU(ADDRESS64) targets for OS(DARWIN). No sane pointer should be in the lowest 4G address region.

This also helps the disassembler more quickly filter out constant values that
aren't pointers.

This change affects DFG's speculationFromCell(), which is the only place that
may affect user facing performance. However, I think the impact should be
insignificant (since the added check is cheap).

  • assembler/JITOperationList.cpp:

(JSC::JITOperationList::populatePointersInJavaScriptCore):
(JSC::llintOperations):
(JSC::JITOperationList::populatePointersInJavaScriptCoreForLLInt):
(JSC::JITOperationList::addDisassemblyLabels):
(JSC::JITOperationList::populateDisassemblyLabelsInJavaScriptCore):
(JSC::JITOperationList::populateDisassemblyLabelsInJavaScriptCoreForLLInt):
(JSC::JITOperationList::populateDisassemblyLabelsInEmbedder):

  • assembler/JITOperationList.h:

(JSC::JITOperationList::populatePointersInJavaScriptCore):
(JSC::JITOperationList::populatePointersInJavaScriptCoreForLLInt):

  • assembler/JITOperationValidation.h:
  • assembler/LinkBuffer.cpp:

(JSC::LinkBuffer::finalizeCodeWithDisassemblyImpl):

  • b3/testb3_1.cpp:

(main):

  • disassembler/ARM64/A64DOpcode.cpp:

(JSC::ARM64Disassembler::A64DOpcode::appendPCRelativeOffset):
(JSC::ARM64Disassembler::MoveWideFormatTrait::rejectedResult):
(JSC::ARM64Disassembler::MoveWideFormatTrait::acceptedResult):
(JSC::ARM64Disassembler::MoveWideIsValidTrait::rejectedResult):
(JSC::ARM64Disassembler::MoveWideIsValidTrait::acceptedResult):
(JSC::ARM64Disassembler::A64DOpcodeMoveWide::handlePotentialDataPointer):
(JSC::ARM64Disassembler::A64DOpcodeMoveWide::handlePotentialPtrTag):
(JSC::ARM64Disassembler::A64DOpcodeMoveWide::parse):
(JSC::ARM64Disassembler::A64DOpcodeMoveWide::format):
(JSC::ARM64Disassembler::A64DOpcodeMoveWide::isValid):

  • disassembler/ARM64/A64DOpcode.h:

(JSC::ARM64Disassembler::A64DOpcodeMoveWide::baseFormat):
(JSC::ARM64Disassembler::A64DOpcodeMoveWide::formatBuffer):

  • disassembler/Disassembler.cpp:

(JSC::Disassembler::ensureLabelMap):
(JSC::registerLabel):
(JSC::labelFor):
(JSC::ensureThunkLabelMap): Deleted.
(JSC::registerThunkLabel): Deleted.
(JSC::labelForThunk): Deleted.

  • disassembler/Disassembler.h:
  • jsc.cpp:

(jscmain):

  • runtime/Gate.h:
  • runtime/JSCPtrTag.cpp:

(JSC::ptrTagName):

  • runtime/JSCPtrTag.h:
  • runtime/Options.cpp:

(JSC::Options::recomputeDependentOptions):

  • runtime/OptionsList.h:
  • runtime/VM.cpp:

(JSC::VM::isScratchBuffer):

  • runtime/VM.h:
  • tools/Integrity.h:

(JSC::Integrity::isSanePointer):

Source/WebCore:

  • bindings/js/WebCoreJITOperations.cpp:

(WebCore::populateJITOperations):
(WebCore::populateDisassemblyLabels):

  • bindings/js/WebCoreJITOperations.h:

(WebCore::populateDisassemblyLabels):
(WebCore::populateJITOperations):

  • testing/js/WebCoreTestSupport.cpp:

(WebCoreTestSupport::populateJITOperations):
(WebCoreTestSupport::populateDisassemblyLabels):

  • testing/js/WebCoreTestSupport.h:

(WebCoreTestSupport::populateDisassemblyLabels):
(WebCoreTestSupport::populateJITOperations):

Source/WTF:

  1. Added a ENABLE(JIT_OPERATION_DISASSEMBLY) flag. Currently, this feature relies on an USE(APPLE_INTERNAL_SDK) for enumerating JIT operations similar to ENABLE(JIT_OPERATION_VALIDATION). It is also restricted to ENABLE(DISASSEMBLER) && CPU(ARM64E).
  • wtf/PlatformCallingConventions.h:
  • wtf/PlatformEnable.h:
Location:
trunk/Source
Files:
28 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r294284 r294287  
     12022-05-16  Mark Lam  <mark.lam@apple.com>
     2
     3        Add ARM64 disassembler support for symbolic dumping of some well known constants.
     4        https://bugs.webkit.org/show_bug.cgi?id=240443
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        1. Added a Options::needDisassemblySupport() option.  This option is true if
     9           any of the JSC disassembly options are enabled.  This allows us to trivially
     10           check if we need to enable additional infrastructure (like those added in this
     11           patch) to support disassembly.
     12
     13        2. Refactor the Disassembler's thunkLabelMap into a more generic labelMap.  It
     14           can now map a pointer to a CString or a const char* label.
     15
     16        3. Enable JITOperationList infrastructure when ENABLE(JIT_OPERATION_DISASSEMBLY)
     17           is true.  This adds a name to the JITOperationAnnotation record.  Since this is
     18           guarded by ENABLE(JIT_OPERATION_DISASSEMBLY), we can trivially turn this part
     19           off later if adding this name adds too much size burden (or if any unexpected
     20           issues arise).  Turning this off will only disable disassembly of JIT operation
     21           names.  Disassembly of other constants (see below) will still be supported.
     22
     23           If Options::needDisassemblySupport() is true, the JITOperationList will
     24           register all JIT operations (and the LLInt ones as well) with the Disassembler
     25           labelMap.
     26
     27        4. Removed the < > brackets around branch target labels except for internal pc
     28           index labels (e.g. <716>) and <unknown> (when we don't know what the branch
     29           target is).  The < > notation takes up space and doesn't add any info.  The
     30           branch targets now look like this:
     31
     32              <32> 0x1180102c0:    b.ne     0x1180101c0 -> thunk: native Tail With Saved Tags Call trampoline
     33              <92> 0x11801c87c:    b        0x118008980 -> thunk: LLInt function for call jump to prologue thunk
     34            <3508> 0x1198e16b4:    b        0x1198bc1a0 -> JIT PC
     35
     36           Internal pc index labels will still use the < > brackets:
     37
     38            <3476> 0x1198e1694:    b.eq     0x1198e16a0 -> <3488>
     39
     40        5. Added ARM64 disassembler support to compute the value of a constant being
     41           loaded into a register using "MoveWide" instructions e.g. movz and movk.
     42
     43           When the disassembler sees a movz or movn or mov (of the MoveWide variety),
     44           the disassembler initializes a m_builtConstant value.  With each subsequent
     45           movk instruction with the same destination register, the disassembler splices
     46           in the corresponding 16-bit immediate.
     47
     48           After disassembling a MoveWide instruction, it will check if the next
     49           instruction is also a MoveWide instruction targeting the same destination
     50           register.  If so, the constant is still being build: hence, it does nothing and
     51           continues.
     52
     53           If the next instruction is (a) a MoveWide instruction targeting a different
     54           register, (b) not a MoveWide instruction, or (c) we've reached the end of the
     55           LinkBuffer (i.e. there's no next instruction), then the constant building for
     56           the current target register is complete.
     57
     58        6. Added ARM64 disassembler support for looking up constants (built in (5) above)
     59           and printing symbolic info / names of those constants.
     60
     61           With ENABLE(JIT_OPERATION_DISASSEMBLY), we now have JIT operation names e.g.
     62
     63             <176> 0x118010270:    movk     x3, #0x9f6e, lsl #48 -> 0x102dc8950 operationVMHandleException
     64             <164> 0x1180180a4:    movk     x8, #0xe5c, lsl #48 -> 0x102db9420 operationVirtualCall
     65
     66           Apart from looking up the constant in the Disassembler labelMap, it also looks
     67           up some commonly used constants e.g.
     68
     69           a. VM pointers:
     70
     71             <156> 0x11801105c:    movk     x0, #0x1, lsl #32 -> 0x139435000 vm
     72
     73           b. Some VM internal pointers (more can be added later as needed):
     74
     75              <24> 0x118014d18:    movk     x17, #0x1, lsl #32 -> 0x13943ee78 vm +40568: vm.topCallFrame
     76              <76> 0x118014d4c:    movk     x17, #0x1, lsl #32 -> 0x139441a10 vm +51728: vm.m_exception
     77             <196> 0x118011244:    movk     x17, #0x1, lsl #32 -> 0x1394417d0 vm +51152: vm.targetMachinePCForThrow
     78             <208> 0x1198e09d0:    movk     x17, #0x1, lsl #32 -> 0x104432cc0 vm +52416: vm.m_doesGC
     79
     80           c. VM related pointers (only 1 for now; not VM fields, but hangs off of VM):
     81
     82              <12> 0x11801938c:    movk     x1, #0x1, lsl #32 -> 0x1052cd3c8 vm scratchBuffer.m_buffer
     83
     84           d. Well known PtrTags:
     85
     86             <204> 0x11801124c:    movz     x16, #0x6f9b -> 0x6f9b ExceptionHandlerPtrTag ?
     87             <212> 0x1180150d4:    movz     x16, #0x593 -> 0x593 JSEntryPtrTag ?
     88             <168> 0x1180183a8:    movz     lr, #0xb389 -> 0xb389 OperationPtrTag ?
     89
     90             * the ? is because we cannot be certain that the 16-bit constant is a PtrTag.
     91               It may just be a coincidence that the value is the same.  However, the user
     92               can trivially look at the surrounding disassembled code, and be able to
     93               tell if the value is used as a PtrTag.
     94
     95           For constants that are not found in the known sets:
     96
     97           e. Small 16-bit constant (prints decimal value for convenience):
     98
     99             <200> 0x1198e09c8:    movz     x17, #0x2cc0 -> 11456
     100
     101           f. Unknown pointers that aren't in the JIT and LLINT regions will simply print
     102              the pointer / constant:
     103
     104              <88> 0x1198e0958:    movz     x17, #0x2088
     105              <92> 0x1198e095c:    movk     x17, #0x30d, lsl #16
     106              <96> 0x1198e0960:    movk     x17, #0x1, lsl #32 -> 0x1030d2088
     107
     108              <unknown> is only used in relative branches.
     109
     110        7. Enhanced the Integrity::isSanePointer() check to reject pointer values that
     111           are less than 4G on CPU(ADDRESS64) targets for OS(DARWIN).  No sane pointer
     112           should be in the lowest 4G address region.
     113
     114           This also helps the disassembler more quickly filter out constant values that
     115           aren't pointers.
     116
     117           This change affects DFG's speculationFromCell(), which is the only place that
     118           may affect user facing performance.  However, I think the impact should be
     119           insignificant (since the added check is cheap).
     120
     121        * assembler/JITOperationList.cpp:
     122        (JSC::JITOperationList::populatePointersInJavaScriptCore):
     123        (JSC::llintOperations):
     124        (JSC::JITOperationList::populatePointersInJavaScriptCoreForLLInt):
     125        (JSC::JITOperationList::addDisassemblyLabels):
     126        (JSC::JITOperationList::populateDisassemblyLabelsInJavaScriptCore):
     127        (JSC::JITOperationList::populateDisassemblyLabelsInJavaScriptCoreForLLInt):
     128        (JSC::JITOperationList::populateDisassemblyLabelsInEmbedder):
     129        * assembler/JITOperationList.h:
     130        (JSC::JITOperationList::populatePointersInJavaScriptCore):
     131        (JSC::JITOperationList::populatePointersInJavaScriptCoreForLLInt):
     132        * assembler/JITOperationValidation.h:
     133        * assembler/LinkBuffer.cpp:
     134        (JSC::LinkBuffer::finalizeCodeWithDisassemblyImpl):
     135        * b3/testb3_1.cpp:
     136        (main):
     137        * disassembler/ARM64/A64DOpcode.cpp:
     138        (JSC::ARM64Disassembler::A64DOpcode::appendPCRelativeOffset):
     139        (JSC::ARM64Disassembler::MoveWideFormatTrait::rejectedResult):
     140        (JSC::ARM64Disassembler::MoveWideFormatTrait::acceptedResult):
     141        (JSC::ARM64Disassembler::MoveWideIsValidTrait::rejectedResult):
     142        (JSC::ARM64Disassembler::MoveWideIsValidTrait::acceptedResult):
     143        (JSC::ARM64Disassembler::A64DOpcodeMoveWide::handlePotentialDataPointer):
     144        (JSC::ARM64Disassembler::A64DOpcodeMoveWide::handlePotentialPtrTag):
     145        (JSC::ARM64Disassembler::A64DOpcodeMoveWide::parse):
     146        (JSC::ARM64Disassembler::A64DOpcodeMoveWide::format):
     147        (JSC::ARM64Disassembler::A64DOpcodeMoveWide::isValid):
     148        * disassembler/ARM64/A64DOpcode.h:
     149        (JSC::ARM64Disassembler::A64DOpcodeMoveWide::baseFormat):
     150        (JSC::ARM64Disassembler::A64DOpcodeMoveWide::formatBuffer):
     151        * disassembler/Disassembler.cpp:
     152        (JSC::Disassembler::ensureLabelMap):
     153        (JSC::registerLabel):
     154        (JSC::labelFor):
     155        (JSC::ensureThunkLabelMap): Deleted.
     156        (JSC::registerThunkLabel): Deleted.
     157        (JSC::labelForThunk): Deleted.
     158        * disassembler/Disassembler.h:
     159        * jsc.cpp:
     160        (jscmain):
     161        * runtime/Gate.h:
     162        * runtime/JSCPtrTag.cpp:
     163        (JSC::ptrTagName):
     164        * runtime/JSCPtrTag.h:
     165        * runtime/Options.cpp:
     166        (JSC::Options::recomputeDependentOptions):
     167        * runtime/OptionsList.h:
     168        * runtime/VM.cpp:
     169        (JSC::VM::isScratchBuffer):
     170        * runtime/VM.h:
     171        * tools/Integrity.h:
     172        (JSC::Integrity::isSanePointer):
     173
    11742022-05-16  Saam Barati  <sbarati@apple.com>
    2175
  • trunk/Source/JavaScriptCore/assembler/JITOperationList.cpp

    r290873 r294287  
    11/*
    2  * Copyright (C) 2020-2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#include "JITOperationList.h"
    2828
     29#include "Disassembler.h"
    2930#include "Gate.h"
    3031#include "JITOperationValidation.h"
    3132#include "LLIntData.h"
    3233#include "Opcode.h"
     34#include "Options.h"
    3335
    3436namespace JSC {
    3537
    36 #if ENABLE(JIT_OPERATION_VALIDATION)
     38#if ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
    3739
    3840LazyNeverDestroyed<JITOperationList> jitOperationList;
     
    4547    jitOperationList.construct();
    4648}
     49
     50#if ENABLE(JIT_OPERATION_VALIDATION)
    4751
    4852#if JIT_OPERATION_VALIDATION_ASSERT_ENABLED
     
    8690        if (Options::useJIT())
    8791            jitOperationList->addPointers(&startOfJITOperationsInJSC, &endOfJITOperationsInJSC);
    88     });
    89 }
     92#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     93        if (UNLIKELY(Options::needDisassemblySupport()))
     94            populateDisassemblyLabelsInJavaScriptCore();
     95#endif
     96    });
     97}
     98
     99#endif // ENABLE(JIT_OPERATION_VALIDATION)
    90100
    91101LLINT_DECLARE_ROUTINE_VALIDATE(llint_function_for_call_prologue);
     
    105115LLINT_DECLARE_ROUTINE_VALIDATE(fuzzer_return_early_from_loop_hint);
    106116
    107 void JITOperationList::populatePointersInJavaScriptCoreForLLInt()
    108 {
    109     static std::once_flag onceKey;
    110     std::call_once(onceKey, [] {
     117#if ENABLE(JIT_OPERATION_VALIDATION) && ENABLE(JIT_OPERATION_DISASSEMBLY)
     118#define LLINT_OP_EXTRAS(validateLabel, nameStr) bitwise_cast<void*>(validateLabel), nameStr
     119#elif ENABLE(JIT_OPERATION_VALIDATION)
     120#define LLINT_OP_EXTRAS(validateLabel, nameStr) bitwise_cast<void*>(validateLabel)
     121#else // ENABLE(JIT_OPERATION_DISASSEMBLY)
     122#define LLINT_OP_EXTRAS(validateLabel, nameStr) nameStr
     123#endif
    111124
    112125#define LLINT_ROUTINE(functionName) { \
    113126        bitwise_cast<void*>(LLInt::getCodeFunctionPtr<CFunctionPtrTag>(functionName)), \
    114         bitwise_cast<void*>(LLINT_ROUTINE_VALIDATE(functionName)) \
     127        LLINT_OP_EXTRAS(LLINT_ROUTINE_VALIDATE(functionName), #functionName) \
    115128    },
    116129
    117130#define LLINT_OP(name) { \
    118131        bitwise_cast<void*>(LLInt::getCodeFunctionPtr<CFunctionPtrTag>(name)), \
    119         bitwise_cast<void*>(LLINT_RETURN_VALIDATE(name)) \
     132        LLINT_OP_EXTRAS(LLINT_RETURN_VALIDATE(name), #name) \
    120133    }, { \
    121134        bitwise_cast<void*>(LLInt::getWide16CodeFunctionPtr<CFunctionPtrTag>(name)), \
    122         bitwise_cast<void*>(LLINT_RETURN_WIDE16_VALIDATE(name)) \
     135        LLINT_OP_EXTRAS(LLINT_RETURN_WIDE16_VALIDATE(name), #name " [wide16]") \
    123136    }, { \
    124137        bitwise_cast<void*>(LLInt::getWide32CodeFunctionPtr<CFunctionPtrTag>(name)), \
    125         bitwise_cast<void*>(LLINT_RETURN_WIDE32_VALIDATE(name)) \
     138        LLINT_OP_EXTRAS(LLINT_RETURN_WIDE32_VALIDATE(name), #name " [wide32]") \
    126139    },
    127140
     
    129142    LLINT_OP(name##_return_location)
    130143
    131         const JITOperationAnnotation operations[] = {
     144struct LLIntOperations {
     145    const JITOperationAnnotation* operations;
     146    size_t numberOfOperations;
     147};
     148
     149static LLIntOperations llintOperations()
     150{
     151    static const JITOperationAnnotation* operations = nullptr;
     152    static size_t numberOfOperations = 0;
     153    static std::once_flag onceKey;
     154    std::call_once(onceKey, [&] {
     155        static const JITOperationAnnotation operationsStorage[] = {
    132156            LLINT_ROUTINE(llint_function_for_call_prologue)
    133157            LLINT_ROUTINE(llint_function_for_construct_prologue)
     
    161185            JSC_WASM_GATE_OPCODES(LLINT_RETURN_LOCATION)
    162186        };
    163         if (Options::useJIT())
    164             jitOperationList->addPointers(operations, operations + WTF_ARRAY_LENGTH(operations));
     187        operations = operationsStorage;
     188        numberOfOperations = WTF_ARRAY_LENGTH(operationsStorage);
     189    });
     190    return { operations, numberOfOperations };
     191}
     192
    165193#undef LLINT_ROUTINE
    166194#undef LLINT_OP
    167195#undef LLINT_RETURN_LOCATION
    168     });
    169 }
    170 
     196#undef LLINT_OP_EXTRAS
     197
     198#if ENABLE(JIT_OPERATION_VALIDATION)
     199
     200void JITOperationList::populatePointersInJavaScriptCoreForLLInt()
     201{
     202    static std::once_flag onceKey;
     203    std::call_once(onceKey, [] {
     204        if (Options::useJIT()) {
     205            auto list = llintOperations();
     206            jitOperationList->addPointers(list.operations, list.operations + list.numberOfOperations);
     207        }
     208#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     209        if (UNLIKELY(Options::needDisassemblySupport()))
     210            JITOperationList::populateDisassemblyLabelsInJavaScriptCoreForLLInt();
     211#endif
     212    });
     213}
    171214
    172215void JITOperationList::populatePointersInEmbedder(const JITOperationAnnotation* beginOperations, const JITOperationAnnotation* endOperations)
     
    178221#endif // ENABLE(JIT_OPERATION_VALIDATION)
    179222
     223#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     224
     225SUPPRESS_ASAN void JITOperationList::addDisassemblyLabels(const JITOperationAnnotation* begin, const JITOperationAnnotation* end)
     226{
     227    RELEASE_ASSERT(Options::needDisassemblySupport());
     228    for (const auto* current = begin; current != end; ++current) {
     229#if ENABLE(JIT_OPERATION_VALIDATION)
     230        auto* operation = current->operationWithValidation;
     231#else
     232        auto* operation = current->operation;
     233#endif
     234        registerLabel(removeCodePtrTag(operation), current->name);
     235    }
     236}
     237
     238void JITOperationList::populateDisassemblyLabelsInJavaScriptCore()
     239{
     240    ASSERT(Options::needDisassemblySupport());
     241    static std::once_flag onceKey;
     242    std::call_once(onceKey, [] {
     243        if (Options::useJIT())
     244            addDisassemblyLabels(&startOfJITOperationsInJSC, &endOfJITOperationsInJSC);
     245    });
     246}
     247
     248void JITOperationList::populateDisassemblyLabelsInJavaScriptCoreForLLInt()
     249{
     250    ASSERT(Options::needDisassemblySupport());
     251    static std::once_flag onceKey;
     252    std::call_once(onceKey, [] {
     253        if (Options::useJIT()) {
     254            auto list = llintOperations();
     255            addDisassemblyLabels(list.operations, list.operations + list.numberOfOperations);
     256        }
     257    });
     258}
     259
     260void JITOperationList::populateDisassemblyLabelsInEmbedder(const JITOperationAnnotation* beginOperations, const JITOperationAnnotation* endOperations)
     261{
     262    if (LIKELY(!Options::needDisassemblySupport()))
     263        return;
     264    if (Options::useJIT())
     265        addDisassemblyLabels(beginOperations, endOperations);
     266}
     267
     268#endif // ENABLE(JIT_OPERATION_DISASSEMBLY)
     269
     270#endif // ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
     271
    180272} // namespace JSC
  • trunk/Source/JavaScriptCore/assembler/JITOperationList.h

    r281910 r294287  
    11/*
    2  * Copyright (C) 2020-2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3333namespace JSC {
    3434
    35 #if ENABLE(JIT_OPERATION_VALIDATION)
     35#if ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
    3636
    3737// This indirection is provided so that we can manually force on assertions for
     
    4646    static void initialize();
    4747
     48#if ENABLE(JIT_OPERATION_VALIDATION)
    4849    template<typename PtrType>
    4950    void* map(PtrType pointer) const
     
    5960    }
    6061#endif
     62#endif // ENABLE(JIT_OPERATION_VALIDATION)
    6163
    6264    static void populatePointersInJavaScriptCore();
     
    6466
    6567    JS_EXPORT_PRIVATE static void populatePointersInEmbedder(const JITOperationAnnotation* beginOperations, const JITOperationAnnotation* endOperations);
     68
     69#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     70    JS_EXPORT_PRIVATE static void populateDisassemblyLabelsInEmbedder(const JITOperationAnnotation* beginOperations, const JITOperationAnnotation* endOperations);
     71#endif
    6672
    6773    template<typename T> static void assertIsJITOperation(T function)
     
    8288
    8389private:
     90#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     91    static void populateDisassemblyLabelsInJavaScriptCore();
     92    static void populateDisassemblyLabelsInJavaScriptCoreForLLInt();
     93    static void addDisassemblyLabels(const JITOperationAnnotation* begin, const JITOperationAnnotation* end);
     94#endif
     95
     96#if ENABLE(JIT_OPERATION_VALIDATION)
    8497    ALWAYS_INLINE void addPointers(const JITOperationAnnotation* begin, const JITOperationAnnotation* end);
    8598
     
    92105    HashMap<void*, void*> m_validatedOperationsInverseMap;
    93106#endif
     107#endif // ENABLE(JIT_OPERATION_VALIDATION)
    94108};
     109
     110#if ENABLE(JIT_OPERATION_VALIDATION)
    95111
    96112JS_EXPORT_PRIVATE extern LazyNeverDestroyed<JITOperationList> jitOperationList;
     
    102118
    103119#else // not ENABLE(JIT_OPERATION_VALIDATION)
     120
     121ALWAYS_INLINE void JITOperationList::populatePointersInJavaScriptCore()
     122{
     123    if (UNLIKELY(Options::needDisassemblySupport()))
     124        populateDisassemblyLabelsInJavaScriptCore();
     125}
     126
     127ALWAYS_INLINE void JITOperationList::populatePointersInJavaScriptCoreForLLInt()
     128{
     129    if (UNLIKELY(Options::needDisassemblySupport()))
     130        populateDisassemblyLabelsInJavaScriptCoreForLLInt();
     131}
     132
     133#endif // ENABLE(JIT_OPERATION_VALIDATION)
     134
     135#else // not ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
    104136
    105137class JITOperationList {
     
    114146};
    115147
    116 #endif // ENABLE(JIT_OPERATION_VALIDATION)
     148#endif // ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
    117149
    118150} // namespace JSC
  • trunk/Source/JavaScriptCore/assembler/JITOperationValidation.h

    r281910 r294287  
    11/*
    2  * Copyright (C) 2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2021-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4848namespace JSC {
    4949
    50 #if ENABLE(JIT_OPERATION_VALIDATION)
    51 
    5250struct JITOperationAnnotation {
    5351    void* operation;
     52#if ENABLE(JIT_OPERATION_VALIDATION)
    5453    void* operationWithValidation;
     54#endif
     55#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     56    const char* name;
     57#endif
    5558};
     59
     60#if ENABLE(JIT_OPERATION_VALIDATION)
    5661
    5762#ifndef JSC_DECLARE_JIT_OPERATION_VALIDATION
  • trunk/Source/JavaScriptCore/assembler/LinkBuffer.cpp

    r294180 r294287  
    8383        va_end(preflightArgs);
    8484
     85        const char prefix[] = "thunk: ";
    8586        char* buffer = 0;
    86         CString label = CString::newUninitialized(stringLength + 1, buffer);
    87         vsnprintf(buffer, stringLength + 1, format, argList);
    88         buffer[stringLength] = '\0';
     87        size_t length = stringLength + sizeof(prefix);
     88        CString label = CString::newUninitialized(length, buffer);
     89        snprintf(buffer, length, "%s", prefix);
     90        vsnprintf(buffer + sizeof(prefix) - 1, stringLength + 1, format, argList);
    8991        out.printf("%s", buffer);
    9092
    91         registerThunkLabel(result.code().untaggedExecutableAddress(), WTFMove(label));
     93        registerLabel(result.code().untaggedExecutableAddress(), WTFMove(label));
    9294    } else
    9395        out.vprintf(format, argList);
  • trunk/Source/JavaScriptCore/b3/testb3_1.cpp

    r292475 r294287  
    11/*
    2  * Copyright (C) 2015-2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    904904#endif // ENABLE(B3_JIT)
    905905
    906 #if ENABLE(JIT_OPERATION_VALIDATION)
     906#if ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
    907907extern const JSC::JITOperationAnnotation startOfJITOperationsInTestB3 __asm("section$start$__DATA_CONST$__jsc_ops");
    908908extern const JSC::JITOperationAnnotation endOfJITOperationsInTestB3 __asm("section$end$__DATA_CONST$__jsc_ops");
     
    931931    JSC::JITOperationList::populatePointersInEmbedder(&startOfJITOperationsInTestB3, &endOfJITOperationsInTestB3);
    932932#endif
    933    
     933#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     934    if (UNLIKELY(JSC::Options::needDisassemblySupport()))
     935        JSC::JITOperationList::populateDisassemblyLabelsInEmbedder(&startOfJITOperationsInTestB3, &endOfJITOperationsInTestB3);
     936#endif
     937
    934938    for (unsigned i = 0; i <= 2; ++i) {
    935939        JSC::Options::defaultB3OptLevel() = i;
  • trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.cpp

    r294180 r294287  
    3333#include "ExecutableAllocator.h"
    3434#include "GPRInfo.h"
     35#include "Integrity.h"
     36#include "JSCJSValue.h"
    3537#include "LLIntPCRanges.h"
     38#include "PureNaN.h"
     39#include "VMInspector.h"
    3640#include <stdarg.h>
    3741#include <stdint.h>
    3842#include <stdio.h>
     43#include <wtf/PtrTag.h>
     44#include <wtf/Range.h>
    3945
    4046namespace JSC { namespace ARM64Disassembler {
     
    202208    else if (targetPC >= m_startPC && targetPC < m_endPC)
    203209        snprintf(buffer, bufferSize - 1, " -> <%u>", static_cast<unsigned>((targetPC - m_startPC) * sizeof(uint32_t)));
    204     else if (const char* thunkLabel = labelForThunk(targetPC))
    205         snprintf(buffer, bufferSize - 1, " -> <thunk: %s>", thunkLabel);
     210    else if (const char* label = labelFor(targetPC))
     211        snprintf(buffer, bufferSize - 1, " -> %s", label);
    206212    else if (isJITPC(targetPC))
    207         targetInfo = " -> <JIT PC>";
     213        targetInfo = " -> JIT PC";
    208214    else if (LLInt::isLLIntPC(targetPC))
    209         targetInfo = " -> <LLInt PC>";
     215        targetInfo = " -> LLInt PC";
    210216    else
    211217        targetInfo = " -> <unknown>";
     
    15711577const char* const A64DOpcodeMoveWide::s_opNames[4] = { "movn", 0, "movz", "movk" };
    15721578
    1573 const char* A64DOpcodeMoveWide::format()
     1579class MoveWideFormatTrait {
     1580public:
     1581    using ResultType = const char*;
     1582    static constexpr bool returnEarlyIfAccepted = false;
     1583
     1584    ALWAYS_INLINE static const char* rejectedResult(A64DOpcodeMoveWide* opcode) { return opcode->baseFormat(); }
     1585    ALWAYS_INLINE static const char* acceptedResult(A64DOpcodeMoveWide* opcode) { return opcode->formatBuffer(); }
     1586};
     1587
     1588class MoveWideIsValidTrait {
     1589public:
     1590    using ResultType = bool;
     1591    static constexpr bool returnEarlyIfAccepted = true;
     1592
     1593    static constexpr bool rejectedResult(A64DOpcodeMoveWide*) { return false; }
     1594    static constexpr bool acceptedResult(A64DOpcodeMoveWide*) { return true; }
     1595};
     1596
     1597bool A64DOpcodeMoveWide::handlePotentialDataPointer(void* ptr)
     1598{
     1599    ASSERT(Integrity::isSanePointer(ptr));
     1600
     1601    bool handled = false;
     1602    VMInspector::forEachVM([&] (VM& vm) {
     1603        if (ptr == &vm) {
     1604            bufferPrintf(" vm");
     1605            handled = true;
     1606            return IterationStatus::Done;
     1607        }
     1608
     1609        if (!vm.isInService())
     1610            return IterationStatus::Continue;
     1611
     1612        auto* vmStart = reinterpret_cast<uint8_t*>(&vm);
     1613        auto* vmEnd = vmStart + sizeof(VM);
     1614        auto* u8Ptr = reinterpret_cast<uint8_t*>(ptr);
     1615        Range vmRange(vmStart, vmEnd);
     1616        if (vmRange.contains(u8Ptr)) {
     1617            unsigned offset = u8Ptr - vmStart;
     1618            bufferPrintf(" vm +%u", offset);
     1619
     1620            const char* description = nullptr;
     1621            if (ptr == &vm.topCallFrame)
     1622                description = "vm.topCallFrame";
     1623            else if (offset == VM::topEntryFrameOffset())
     1624                description = "vm.topEntryFrame";
     1625            else if (offset == VM::exceptionOffset())
     1626                description = "vm.m_exception";
     1627            else if (offset == VM::offsetOfHeapBarrierThreshold())
     1628                description = "vm.heap.m_barrierThreshold";
     1629            else if (offset == VM::callFrameForCatchOffset())
     1630                description = "vm.callFrameForCatch";
     1631            else if (ptr == vm.addressOfSoftStackLimit())
     1632                description = "vm.m_softStackLimit";
     1633            else if (ptr == &vm.osrExitIndex)
     1634                description = "vm.osrExitIndex";
     1635            else if (ptr == &vm.osrExitJumpDestination)
     1636                description = "vm.osrExitJumpDestination";
     1637            else if (ptr == vm.smallStrings.singleCharacterStrings())
     1638                description = "vm.smallStrings.m_singleCharacterStrings";
     1639            else if (ptr == &vm.targetMachinePCForThrow)
     1640                description = "vm.targetMachinePCForThrow";
     1641            else if (ptr == vm.traps().trapBitsAddress())
     1642                description = "vm.m_traps.m_trapBits";
     1643#if ENABLE(DFG_DOES_GC_VALIDATION)
     1644            else if (ptr == vm.addressOfDoesGC())
     1645                description = "vm.m_doesGC";
     1646#endif
     1647            if (description)
     1648                bufferPrintf(": %s", description);
     1649
     1650            handled = true;
     1651            return IterationStatus::Done;
     1652        }
     1653
     1654        if (vm.isScratchBuffer(ptr)) {
     1655            bufferPrintf(" vm scratchBuffer.m_buffer");
     1656            handled = true;
     1657            return IterationStatus::Done;
     1658        }
     1659        return IterationStatus::Continue;
     1660    });
     1661    return handled;
     1662}
     1663
     1664#if CPU(ARM64E)
     1665bool A64DOpcodeMoveWide::handlePotentialPtrTag(uintptr_t value)
     1666{
     1667    if (!value || value > 0xffff)
     1668        return false;
     1669
     1670    PtrTag tag = static_cast<PtrTag>(value);
     1671#if ENABLE(PTRTAG_DEBUGGING)
     1672    const char* name = WTF::ptrTagName(tag);
     1673    if (name[0] == '<')
     1674        return false; // Only result that starts with '<' is "<unknown>".
     1675#else
     1676    // Without ENABLE(PTRTAG_DEBUGGING), not all PtrTags are registeredf for
     1677    // printing. So, we'll just do the minimum with only the JSC specific tags.
     1678    const char* name = ptrTagName(tag);
     1679    if (!name)
     1680        return false;
     1681#endif
     1682
     1683    // Also print '?' to indicate that this is a maybe. We do not know for certain
     1684    // if the constant is meant to be used as a PtrTag.
     1685    bufferPrintf(" -> %p %s ?", reinterpret_cast<void*>(value), name);
     1686    return true;
     1687}
     1688#endif
     1689
     1690template<typename Trait>
     1691typename Trait::ResultType A64DOpcodeMoveWide::parse()
    15741692{
    15751693    if (opc() == 1)
    1576         return A64DOpcode::format();
     1694        return Trait::rejectedResult(this);
    15771695    if (!is64Bit() && hw() >= 2)
    1578         return A64DOpcode::format();
     1696        return Trait::rejectedResult(this);
     1697
     1698    if constexpr (Trait::returnEarlyIfAccepted)
     1699        return Trait::acceptedResult(this);
    15791700
    15801701    if (!opc() && (!immediate16() || !hw()) && (is64Bit() || immediate16() != 0xffff)) {
     
    15881709            amount = ~amount;
    15891710            appendSignedImmediate64(amount);
     1711            m_builtConstant = static_cast<intptr_t>(amount);
    15901712        } else {
    15911713            int32_t amount = immediate16() << (hw() * 16);
    15921714            amount = ~amount;
    15931715            appendSignedImmediate(amount);
     1716            m_builtConstant = static_cast<intptr_t>(amount);
    15941717        }
    15951718    } else {
     
    16021725            appendShiftAmount(hw());
    16031726        }
    1604     }
    1605 
    1606     return m_formatBuffer;
    1607 }
     1727
     1728        if (opc() == 2) // Encoding for movz
     1729            m_builtConstant = 0;
     1730
     1731        unsigned shift = hw() * 16;
     1732        uintptr_t value = static_cast<uintptr_t>(immediate16()) << shift;
     1733        uintptr_t mask = ~(static_cast<uintptr_t>(0xffff) << shift);
     1734        m_builtConstant &= mask;
     1735        m_builtConstant |= value;
     1736    }
     1737
     1738    auto dumpConstantData = [&] {
     1739        uint32_t* nextPC = m_currentPC + 1;
     1740        bool doneBuildingConstant = false;
     1741
     1742        if (nextPC >= m_endPC)
     1743            doneBuildingConstant = true;
     1744        else {
     1745            A64DOpcode nextOpcodeBase(m_startPC, m_endPC);
     1746            A64DOpcodeMoveWide& nextOpcode = *reinterpret_cast<A64DOpcodeMoveWide*>(&nextOpcodeBase);
     1747            nextOpcode.setPCAndOpcode(nextPC, *nextPC);
     1748
     1749            bool nextIsMoveWideGroup = opcodeGroupNumber(m_opcode) == opcodeGroupNumber(*nextPC);
     1750
     1751            if (!nextIsMoveWideGroup || !nextOpcode.isValid() || nextOpcode.rd() != rd())
     1752                doneBuildingConstant = true;
     1753        }
     1754        if (!doneBuildingConstant)
     1755            return;
     1756
     1757        void* ptr = removeCodePtrTag(bitwise_cast<void*>(m_builtConstant));
     1758        if (!ptr)
     1759            return;
     1760
     1761        if (Integrity::isSanePointer(ptr)) {
     1762            bufferPrintf(" -> %p", ptr);
     1763            if (const char* label = labelFor(ptr))
     1764                return bufferPrintf(" %s", label);
     1765            if (isJITPC(ptr))
     1766                return bufferPrintf(" JIT PC");
     1767            if (LLInt::isLLIntPC(ptr))
     1768                return bufferPrintf(" LLInt PC");
     1769            handlePotentialDataPointer(ptr);
     1770            return;
     1771        }
     1772#if CPU(ARM64E)
     1773        if (handlePotentialPtrTag(m_builtConstant))
     1774            return;
     1775#endif
     1776        if (m_builtConstant < 0x10000)
     1777            bufferPrintf(" -> %u", static_cast<unsigned>(m_builtConstant));
     1778        else
     1779            bufferPrintf(" -> %p", reinterpret_cast<void*>(m_builtConstant));
     1780    };
     1781
     1782    if (m_startPC)
     1783        dumpConstantData();
     1784
     1785    return Trait::acceptedResult(this);
     1786}
     1787
     1788const char* A64DOpcodeMoveWide::format() { return parse<MoveWideFormatTrait>(); }
     1789bool A64DOpcodeMoveWide::isValid() { return parse<MoveWideIsValidTrait>(); }
    16081790
    16091791const char* A64DOpcodeTestAndBranchImmediate::format()
  • trunk/Source/JavaScriptCore/disassembler/ARM64/A64DOpcode.h

    r294180 r294287  
    195195    }
    196196
    197     static constexpr int bufferSize = 81;
     197    static constexpr int bufferSize = 101;
    198198
    199199    char m_formatBuffer[bufferSize];
     
    203203    uint32_t m_opcode;
    204204    int m_bufferOffset;
     205    uintptr_t m_builtConstant { 0 };
    205206
    206207private:
     
    873874
    874875    const char* format();
     876    bool isValid();
    875877
    876878    const char* opName() { return s_opNames[opc()]; }
     
    878880    unsigned hw() { return (m_opcode >> 21) & 0x3; }
    879881    unsigned immediate16() { return (m_opcode >> 5) & 0xffff; }
     882
     883private:
     884    template<typename Trait> typename Trait::ResultType parse();
     885    bool handlePotentialDataPointer(void*);
     886    bool handlePotentialPtrTag(uintptr_t);
     887
     888    // These forwarding functions are needed for MoveWideFormatTrait only.
     889    const char* baseFormat() { return A64DOpcode::format(); }
     890    const char* formatBuffer() { return m_formatBuffer; }
     891
     892    friend class MoveWideFormatTrait;
     893    friend class MoveWideIsValidTrait;
    880894};
    881895
  • trunk/Source/JavaScriptCore/disassembler/Disassembler.cpp

    r294180 r294287  
    2828
    2929#include "MacroAssemblerCodeRef.h"
     30#include <variant>
    3031#include <wtf/Condition.h>
    3132#include <wtf/DataLog.h>
     
    3738namespace JSC {
    3839
    39 using ThunkLabelMap = HashMap<void*, CString>;
    40 LazyNeverDestroyed<ThunkLabelMap> thunkLabelMap;
     40namespace Disassembler {
     41
     42Lock labelMapLock;
     43
     44using LabelMap = HashMap<void*, std::variant<CString, const char*>>;
     45LazyNeverDestroyed<LabelMap> labelMap;
     46
     47static LabelMap& ensureLabelMap() WTF_REQUIRES_LOCK(labelMapLock)
     48{
     49    static std::once_flag onceKey;
     50    std::call_once(onceKey, [] {
     51        labelMap.construct();
     52    });
     53    return labelMap.get();
     54}
     55
     56} // namespace Disassembler
    4157
    4258void disassemble(const MacroAssemblerCodePtr<DisassemblyPtrTag>& codePtr, size_t size, void* codeStart, void* codeEnd, const char* prefix, PrintStream& out)
     
    158174}
    159175
    160 static ThunkLabelMap& ensureThunkLabelMap()
    161 {
    162     static std::once_flag onceKey;
    163     std::call_once(onceKey, [] {
    164         thunkLabelMap.construct();
    165     });
    166     return thunkLabelMap.get();
    167 }
    168 
    169 void registerThunkLabel(void* thunkAddress, CString&& label)
    170 {
    171     ensureThunkLabelMap().add(thunkAddress, WTFMove(label));
    172 }
    173 
    174 const char* labelForThunk(void* thunkAddress)
    175 {
    176     auto& map = ensureThunkLabelMap();
     176void registerLabel(void* thunkAddress, CString&& label)
     177{
     178    Locker lock { Disassembler::labelMapLock };
     179    Disassembler::ensureLabelMap().add(thunkAddress, WTFMove(label));
     180}
     181
     182void registerLabel(void* address, const char* label)
     183{
     184    Locker lock { Disassembler::labelMapLock };
     185    Disassembler::ensureLabelMap().add(address, label);
     186}
     187
     188const char* labelFor(void* thunkAddress)
     189{
     190    Locker lock { Disassembler::labelMapLock };
     191    auto& map = Disassembler::ensureLabelMap();
    177192    auto it = map.find(thunkAddress);
    178193    if (it == map.end())
    179194        return nullptr;
    180     return it->value.data();
     195    if (std::holds_alternative<CString>(it->value))
     196        return std::get<CString>(it->value).data();
     197    return std::get<const char*>(it->value);
    181198}
    182199
  • trunk/Source/JavaScriptCore/disassembler/Disassembler.h

    r294180 r294287  
    6262JS_EXPORT_PRIVATE void waitForAsynchronousDisassembly();
    6363
    64 void registerThunkLabel(void* thunkAddress, CString&& label);
    65 const char* labelForThunk(void* thunkAddress);
     64void registerLabel(void* thunkAddress, CString&& label);
     65void registerLabel(void* thunkAddress, const char* label);
     66const char* labelFor(void* thunkAddress);
    6667
    6768} // namespace JSC
  • trunk/Source/JavaScriptCore/jsc.cpp

    r293879 r294287  
    37573757}
    37583758
    3759 #if ENABLE(JIT_OPERATION_VALIDATION)
     3759#if ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
    37603760extern const JITOperationAnnotation startOfJITOperationsInShell __asm("section$start$__DATA_CONST$__jsc_ops");
    37613761extern const JITOperationAnnotation endOfJITOperationsInShell __asm("section$end$__DATA_CONST$__jsc_ops");
     
    37843784    JSC::JITOperationList::populatePointersInEmbedder(&startOfJITOperationsInShell, &endOfJITOperationsInShell);
    37853785#endif
     3786#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     3787    if (UNLIKELY(Options::needDisassemblySupport()))
     3788        JSC::JITOperationList::populateDisassemblyLabelsInEmbedder(&startOfJITOperationsInShell, &endOfJITOperationsInShell);
     3789#endif
     3790
    37863791    initializeTimeoutIfNeeded();
    37873792
  • trunk/Source/JavaScriptCore/runtime/ArrayBuffer.h

    r291331 r294287  
    7373};
    7474
    75 class ArrayBufferContents {
     75class   ArrayBufferContents {
    7676    WTF_MAKE_NONCOPYABLE(ArrayBufferContents);
    7777public:
  • trunk/Source/JavaScriptCore/runtime/Gate.h

    r285795 r294287  
    11/*
    2  * Copyright (C) 2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828namespace JSC {
    2929
    30 #if ENABLE(JIT_OPERATION_VALIDATION) || CPU(ARM64E)
     30#if ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY) || CPU(ARM64E)
    3131
    3232#define JSC_UTILITY_GATES(v) \
     
    9292#undef JSC_COUNT
    9393#undef JSC_OPCODE_COUNT
    94 #else
     94
     95#else // not (ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY) || CPU(ARM64E))
     96
    9597// Keep it non-zero to make JSCConfig's array not [0].
    9698static constexpr unsigned numberOfGates = 1;
    97 #endif
    9899
    99 }
     100#endif // ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY) || CPU(ARM64E)
     101
     102} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSCPtrTag.cpp

    r269353 r294287  
    11/*
    2  * Copyright (C) 2018-2020 Apple Inc. All rights reserved.
     2 * Copyright (C) 2018-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3737namespace JSC {
    3838
    39 #if CPU(ARM64E) && ENABLE(PTRTAG_DEBUGGING)
     39#if ENABLE(JIT_OPERATION_DISASSEMBLY) || (CPU(ARM64E) && ENABLE(PTRTAG_DEBUGGING))
    4040
     41const char* ptrTagName(PtrTag tag)
     42{
     43#define RETURN_PTRTAG_NAME(_tagName, calleeType, callerType) case _tagName: return #_tagName;
     44    switch (static_cast<unsigned>(tag)) {
     45        FOR_EACH_JSC_PTRTAG(RETURN_PTRTAG_NAME)
     46    }
     47#undef RETURN_PTRTAG_NAME
     48    return nullptr; // Matching tag not found.
     49}
     50
     51#if ENABLE(PTRTAG_DEBUGGING)
    4152static const char* tagForPtr(const void* ptr)
    4253{
     
    5162}
    5263
    53 static const char* ptrTagName(PtrTag tag)
    54 {
    55 #define RETURN_PTRTAG_NAME(_tagName, calleeType, callerType) case _tagName: return #_tagName;
    56     switch (static_cast<unsigned>(tag)) {
    57         FOR_EACH_JSC_PTRTAG(RETURN_PTRTAG_NAME)
    58     }
    59 #undef RETURN_PTRTAG_NAME
    60     return nullptr; // Matching tag not found.
    61 }
    62 
    6364void initializePtrTagLookup()
    6465{
     
    6768    WTF::registerPtrTagLookup(&lookup);
    6869}
    69 
    70 #endif // CPU(ARM64E) && ENABLE(PTRTAG_DEBUGGING)
     70#endif // ENABLE(PTRTAG_DEBUGGING)
     71#endif // ENABLE(JIT_OPERATION_DISASSEMBLY) || (CPU(ARM64E) && ENABLE(PTRTAG_DEBUGGING))
    7172
    7273#if CPU(ARM64E)
  • trunk/Source/JavaScriptCore/runtime/JSCPtrTag.h

    r286891 r294287  
    11/*
    2  * Copyright (C) 2018-2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2018-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    249249#endif
    250250
     251#if ENABLE(JIT_OPERATION_DISASSEMBLY) || (CPU(ARM64E) && ENABLE(PTRTAG_DEBUGGING))
     252const char* ptrTagName(PtrTag);
     253#endif
     254
    251255} // namespace JSC
    252256namespace WTF {
  • trunk/Source/JavaScriptCore/runtime/Options.cpp

    r293484 r294287  
    466466        Options::useFastTLSForWasmContext() = false;
    467467   
    468     if (Options::logJIT()
    469         || Options::dumpDisassembly()
     468    if (Options::dumpDisassembly()
     469        || Options::asyncDisassembly()
    470470        || Options::dumpDFGDisassembly()
    471471        || Options::dumpFTLDisassembly()
     472        || Options::dumpRegExpDisassembly()
     473        || Options::dumpWasmDisassembly()
     474        || Options::dumpBBQDisassembly()
     475        || Options::dumpOMGDisassembly())
     476        Options::needDisassemblySupport() = true;
     477
     478    if (Options::logJIT()
     479        || Options::needDisassemblySupport()
    472480        || Options::dumpBytecodeAtDFGTime()
    473481        || Options::dumpGraphAtEachPhase()
  • trunk/Source/JavaScriptCore/runtime/OptionsList.h

    r293473 r294287  
    128128    v(Bool, useOSLog, false, Normal, "Log dataLog()s to os_log instead of stderr") \
    129129    /* dumpDisassembly implies dumpDFGDisassembly. */ \
     130    v(Bool, needDisassemblySupport, false, Normal, nullptr) \
    130131    v(Bool, dumpDisassembly, false, Normal, "dumps disassembly of all JIT compiled code upon compilation") \
    131132    v(Bool, asyncDisassembly, false, Normal, nullptr) \
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r294017 r294287  
    14101410}
    14111411
     1412bool VM::isScratchBuffer(void* ptr)
     1413{
     1414    Locker locker { m_scratchBufferLock };
     1415    for (auto* scratchBuffer : m_scratchBuffers) {
     1416        if (scratchBuffer->dataBuffer() == ptr)
     1417            return true;
     1418    }
     1419    return false;
     1420}
     1421
    14121422void VM::ensureShadowChicken()
    14131423{
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r294017 r294287  
    686686    ScratchBuffer* scratchBufferForSize(size_t size);
    687687    void clearScratchBuffers();
     688    bool isScratchBuffer(void*);
    688689
    689690    EncodedJSValue* exceptionFuzzingBuffer(size_t size)
  • trunk/Source/JavaScriptCore/tools/Integrity.h

    r294017 r294287  
    9595#if CPU(ADDRESS64)
    9696    uintptr_t pointerAsInt = bitwise_cast<uintptr_t>(pointer);
     97#if OS(DARWIN)
     98    constexpr uintptr_t oneAbove4G = (static_cast<uintptr_t>(1) << 32);
     99    if (pointerAsInt < oneAbove4G)
     100        return false;
     101#endif
    97102    uintptr_t canonicalPointerBits = pointerAsInt << (64 - OS_CONSTANT(EFFECTIVE_ADDRESS_WIDTH));
    98103    uintptr_t nonCanonicalPointerBits = pointerAsInt >> OS_CONSTANT(EFFECTIVE_ADDRESS_WIDTH);
     
    101106    UNUSED_PARAM(pointer);
    102107    return true;
    103 #endif
     108#endif // CPU(ADDRESS64)
    104109}
    105110
  • trunk/Source/WTF/ChangeLog

    r294272 r294287  
     12022-05-16  Mark Lam  <mark.lam@apple.com>
     2
     3        Add ARM64 disassembler support for symbolic dumping of some well known constants.
     4        https://bugs.webkit.org/show_bug.cgi?id=240443
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        1. Added a ENABLE(JIT_OPERATION_DISASSEMBLY) flag.
     9           Currently, this feature relies on an USE(APPLE_INTERNAL_SDK) for enumerating
     10           JIT operations similar to ENABLE(JIT_OPERATION_VALIDATION).  It is also
     11           restricted to ENABLE(DISASSEMBLER) && CPU(ARM64E).
     12
     13        * wtf/PlatformCallingConventions.h:
     14        * wtf/PlatformEnable.h:
     15
    1162022-05-16  Brent Fulgham  <bfulgham@apple.com>
    217
  • trunk/Source/WTF/wtf/PlatformCallingConventions.h

    r281910 r294287  
    11/*
    2  * Copyright (C) 2006-2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2006-2022 Apple Inc. All rights reserved.
    33 * Copyright (C) 2007-2009 Torch Mobile, Inc.
    44 * Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved.
     
    8585#endif
    8686
    87 #if ENABLE(JIT_OPERATION_VALIDATION)
     87#if ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
     88
     89#if ENABLE(JIT_OPERATION_VALIDATION) && ENABLE(JIT_OPERATION_DISASSEMBLY)
     90#define JSC_ANNOTATE_JIT_OPERATION_EXTRAS(validateFunction, name) (void*)validateFunction, name
     91#elif ENABLE(JIT_OPERATION_VALIDATION)
     92#define JSC_ANNOTATE_JIT_OPERATION_EXTRAS(validateFunction, name) (void*)validateFunction
     93#else // ENABLE(JIT_OPERATION_DISASSEMBLY)
     94#define JSC_ANNOTATE_JIT_OPERATION_EXTRAS(validateFunction, name) name
     95#endif
     96
    8897#define JSC_ANNOTATE_JIT_OPERATION_INTERNAL(function) \
    89     constexpr JSC::JITOperationAnnotation _JITTargetID_##function __attribute__((used, section("__DATA_CONST,__jsc_ops"))) = { (void*)function, (void*)function##Validate };
     98    constexpr JSC::JITOperationAnnotation _JITTargetID_##function __attribute__((used, section("__DATA_CONST,__jsc_ops"))) = { (void*)function, JSC_ANNOTATE_JIT_OPERATION_EXTRAS(function##Validate, #function) };
    9099
    91100#define JSC_ANNOTATE_JIT_OPERATION(function) \
     
    101110    JSC_ANNOTATE_JIT_OPERATION_INTERNAL(function)
    102111
    103 #else
     112#else // not (ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY))
     113
    104114#define JSC_ANNOTATE_JIT_OPERATION(function)
    105115#define JSC_ANNOTATE_JIT_OPERATION_PROBE(function)
    106116#define JSC_ANNOTATE_JIT_OPERATION_RETURN(function)
    107 #endif
    108117
     118#endif // ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
    109119
    110120#define JSC_DEFINE_JIT_OPERATION_WITHOUT_VARIABLE(functionName, returnType, parameters) \
  • trunk/Source/WTF/wtf/PlatformEnable.h

    r292870 r294287  
    11/*
    2  * Copyright (C) 2006-2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2006-2022 Apple Inc. All rights reserved.
    33 * Copyright (C) 2007-2009 Torch Mobile, Inc.
    44 * Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved.
     
    850850#endif
    851851
     852#if USE(APPLE_INTERNAL_SDK) && ENABLE(DISASSEMBLER) && CPU(ARM64E)
     853#define ENABLE_JIT_OPERATION_DISASSEMBLY 1
     854#endif
     855
    852856#if !defined(ENABLE_BINDING_INTEGRITY) && !OS(WINDOWS)
    853857#define ENABLE_BINDING_INTEGRITY 1
  • trunk/Source/WebCore/ChangeLog

    r294281 r294287  
     12022-05-16  Mark Lam  <mark.lam@apple.com>
     2
     3        Add ARM64 disassembler support for symbolic dumping of some well known constants.
     4        https://bugs.webkit.org/show_bug.cgi?id=240443
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        * bindings/js/WebCoreJITOperations.cpp:
     9        (WebCore::populateJITOperations):
     10        (WebCore::populateDisassemblyLabels):
     11        * bindings/js/WebCoreJITOperations.h:
     12        (WebCore::populateDisassemblyLabels):
     13        (WebCore::populateJITOperations):
     14        * testing/js/WebCoreTestSupport.cpp:
     15        (WebCoreTestSupport::populateJITOperations):
     16        (WebCoreTestSupport::populateDisassemblyLabels):
     17        * testing/js/WebCoreTestSupport.h:
     18        (WebCoreTestSupport::populateDisassemblyLabels):
     19        (WebCoreTestSupport::populateJITOperations):
     20
    1212022-05-16  Gabriel Nava Marino  <gnavamarino@apple.com>
    222
  • trunk/Source/WebCore/bindings/js/WebCoreJITOperations.cpp

    r281910 r294287  
    11/*
    2  * Copyright (C) 2020-2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3131namespace WebCore {
    3232
    33 #if ENABLE(JIT_OPERATION_VALIDATION)
     33#if ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
     34
    3435extern const JSC::JITOperationAnnotation startOfJITOperationsInWebCore __asm("section$start$__DATA_CONST$__jsc_ops");
    3536extern const JSC::JITOperationAnnotation endOfJITOperationsInWebCore __asm("section$end$__DATA_CONST$__jsc_ops");
    3637
     38#if ENABLE(JIT_OPERATION_VALIDATION)
    3739void populateJITOperations()
    3840{
     
    4143        JSC::JITOperationList::populatePointersInEmbedder(&startOfJITOperationsInWebCore, &endOfJITOperationsInWebCore);
    4244    });
     45#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     46    if (UNLIKELY(JSC::Options::needDisassemblySupport()))
     47        populateDisassemblyLabels();
     48#endif
    4349}
    4450#endif // ENABLE(JIT_OPERATION_VALIDATION)
    4551
     52#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     53void populateDisassemblyLabels()
     54{
     55    static std::once_flag onceKey;
     56    std::call_once(onceKey, [] {
     57        JSC::JITOperationList::populateDisassemblyLabelsInEmbedder(&startOfJITOperationsInWebCore, &endOfJITOperationsInWebCore);
     58    });
    4659}
     60#endif // ENABLE(JIT_OPERATION_DISASSEMBLY)
     61
     62#endif // ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
     63
     64}
  • trunk/Source/WebCore/bindings/js/WebCoreJITOperations.h

    r281544 r294287  
    11/*
    2  * Copyright (C) 2020-2021 Apple Inc. All rights reserved.
     2 * Copyright (C) 2020-2022 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828namespace WebCore {
    2929
     30#if ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
     31
     32#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     33WEBCORE_EXPORT void populateDisassemblyLabels();
     34#else
     35inline void populateDisassemblyLabels() { }
     36#endif
     37
    3038#if ENABLE(JIT_OPERATION_VALIDATION)
    3139WEBCORE_EXPORT void populateJITOperations();
    3240#else
    33 inline void populateJITOperations() { }
     41inline void populateJITOperations() { populateDisassemblyLabels(); }
    3442#endif
    3543
     44#else
     45inline void populateJITOperations() { }
     46#endif // ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
     47
    3648}
  • trunk/Source/WebCore/testing/js/WebCoreTestSupport.cpp

    r292793 r294287  
    11/*
    22 * Copyright (C) 2011, 2015 Google Inc. All rights reserved.
    3  * Copyright (C) 2016-2021 Apple Inc. All rights reserved.
     3 * Copyright (C) 2016-2022 Apple Inc. All rights reserved.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
     
    242242#endif
    243243
    244 #if ENABLE(JIT_OPERATION_VALIDATION)
     244#if ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
     245
    245246extern const JSC::JITOperationAnnotation startOfJITOperationsInWebCoreTestSupport __asm("section$start$__DATA_CONST$__jsc_ops");
    246247extern const JSC::JITOperationAnnotation endOfJITOperationsInWebCoreTestSupport __asm("section$end$__DATA_CONST$__jsc_ops");
     248
     249#if ENABLE(JIT_OPERATION_VALIDATION)
    247250
    248251void populateJITOperations()
     
    252255        JSC::JITOperationList::populatePointersInEmbedder(&startOfJITOperationsInWebCoreTestSupport, &endOfJITOperationsInWebCoreTestSupport);
    253256    });
     257#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     258    if (UNLIKELY(JSC::Options::needDisassemblySupport()))
     259        populateDisassemblyLabels();
     260#endif
    254261}
    255262#endif // ENABLE(JIT_OPERATION_VALIDATION)
    256263
    257 }
     264#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     265void populateDisassemblyLabels()
     266{
     267    static std::once_flag onceKey;
     268    std::call_once(onceKey, [] {
     269        JSC::JITOperationList::populateDisassemblyLabelsInEmbedder(&startOfJITOperationsInWebCoreTestSupport, &endOfJITOperationsInWebCoreTestSupport);
     270    });
     271}
     272#endif // ENABLE(JIT_OPERATION_DISASSEMBLY)
     273
     274#endif // ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
     275
     276} // namespace WebCoreTestSupport
  • trunk/Source/WebCore/testing/js/WebCoreTestSupport.h

    r284857 r294287  
    11/*
    22 * Copyright (C) 2011, 2015 Google Inc. All rights reserved.
    3  * Copyright (C) 2016-2021 Apple Inc. All rights reserved.
     3 * Copyright (C) 2016-2022 Apple Inc. All rights reserved.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
     
    6868void setAdditionalSupportedImageTypesForTesting(const String&) TEST_SUPPORT_EXPORT;
    6969
     70#if ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
     71#if ENABLE(JIT_OPERATION_DISASSEMBLY)
     72void populateDisassemblyLabels() TEST_SUPPORT_EXPORT;
     73#else
     74inline void populateDisassemblyLabels() { }
     75#endif
     76
    7077#if ENABLE(JIT_OPERATION_VALIDATION)
    7178void populateJITOperations() TEST_SUPPORT_EXPORT;
    7279#else
    73 inline void populateJITOperations() { }
     80inline void populateJITOperations() { populateDisassemblyLabels(); }
    7481#endif
    7582
     83#else
     84inline void populateJITOperations() { }
     85#endif // ENABLE(JIT_OPERATION_VALIDATION) || ENABLE(JIT_OPERATION_DISASSEMBLY)
     86
    7687} // namespace WebCoreTestSupport
Note: See TracChangeset for help on using the changeset viewer.