Changeset 245432 in webkit


Ignore:
Timestamp:
May 16, 2019 7:21:51 PM (5 years ago)
Author:
keith_miller@apple.com
Message:

Wasm should cage the memory base pointers in structs
https://bugs.webkit.org/show_bug.cgi?id=197620

Reviewed by Saam Barati.

Source/bmalloc:

Fix signature to take Gigacage::Kind, which matches GIGACAGE_ENABLED build.

  • bmalloc/Gigacage.h:

(Gigacage::isEnabled):

Source/JavaScriptCore:

Currently, we use cageConditionally; this only matters for API
users since the web content process cannot disable primitive
gigacage. This patch also adds a set helper for union/intersection
of RegisterSets.

  • assembler/CPU.h:

(JSC::isARM64E):

  • jit/RegisterSet.h:

(JSC::RegisterSet::set):

  • wasm/WasmAirIRGenerator.cpp:

(JSC::Wasm::AirIRGenerator::restoreWebAssemblyGlobalState):
(JSC::Wasm::AirIRGenerator::addCallIndirect):

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::restoreWebAssemblyGlobalState):
(JSC::Wasm::B3IRGenerator::addCallIndirect):

  • wasm/WasmBinding.cpp:

(JSC::Wasm::wasmToWasm):

  • wasm/WasmInstance.h:

(JSC::Wasm::Instance::cachedMemory const):
(JSC::Wasm::Instance::updateCachedMemory):

  • wasm/WasmMemory.cpp:

(JSC::Wasm::Memory::grow):

  • wasm/WasmMemory.h:

(JSC::Wasm::Memory::memory const):

  • wasm/js/JSToWasm.cpp:

(JSC::Wasm::createJSToWasmWrapper):

  • wasm/js/WebAssemblyFunction.cpp:

(JSC::WebAssemblyFunction::jsCallEntrypointSlow):

Source/WTF:

Rename reauthenticate to recage.

  • wtf/CagedPtr.h:

(WTF::CagedPtr::recage):
(WTF::CagedPtr::reauthenticate): Deleted.

Location:
trunk/Source
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r245430 r245432  
     12019-05-16  Keith Miller  <keith_miller@apple.com>
     2
     3        Wasm should cage the memory base pointers in structs
     4        https://bugs.webkit.org/show_bug.cgi?id=197620
     5
     6        Reviewed by Saam Barati.
     7
     8        Currently, we use cageConditionally; this only matters for API
     9        users since the web content process cannot disable primitive
     10        gigacage. This patch also adds a set helper for union/intersection
     11        of RegisterSets.
     12
     13        * assembler/CPU.h:
     14        (JSC::isARM64E):
     15        * jit/RegisterSet.h:
     16        (JSC::RegisterSet::set):
     17        * wasm/WasmAirIRGenerator.cpp:
     18        (JSC::Wasm::AirIRGenerator::restoreWebAssemblyGlobalState):
     19        (JSC::Wasm::AirIRGenerator::addCallIndirect):
     20        * wasm/WasmB3IRGenerator.cpp:
     21        (JSC::Wasm::B3IRGenerator::restoreWebAssemblyGlobalState):
     22        (JSC::Wasm::B3IRGenerator::addCallIndirect):
     23        * wasm/WasmBinding.cpp:
     24        (JSC::Wasm::wasmToWasm):
     25        * wasm/WasmInstance.h:
     26        (JSC::Wasm::Instance::cachedMemory const):
     27        (JSC::Wasm::Instance::updateCachedMemory):
     28        * wasm/WasmMemory.cpp:
     29        (JSC::Wasm::Memory::grow):
     30        * wasm/WasmMemory.h:
     31        (JSC::Wasm::Memory::memory const):
     32        * wasm/js/JSToWasm.cpp:
     33        (JSC::Wasm::createJSToWasmWrapper):
     34        * wasm/js/WebAssemblyFunction.cpp:
     35        (JSC::WebAssemblyFunction::jsCallEntrypointSlow):
     36
    1372019-05-16  David Kilzer  <ddkilzer@apple.com>
    238
  • trunk/Source/JavaScriptCore/assembler/CPU.h

    r244233 r245432  
    5151{
    5252#if CPU(ARM64)
     53    return true;
     54#else
     55    return false;
     56#endif
     57}
     58
     59constexpr bool isARM64E()
     60{
     61#if CPU(ARM64E)
    5362    return true;
    5463#else
  • trunk/Source/JavaScriptCore/jit/RegisterSet.h

    r243886 r245432  
    8585        set(regs.payloadGPR(), value);
    8686    }
    87    
     87
     88    void set(const RegisterSet& other, bool value = true) { value ? merge(other) : exclude(other); }
     89
    8890    void clear(Reg reg)
    8991    {
  • trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp

    r245064 r245432  
    4141#include "B3ProcedureInlines.h"
    4242#include "BinarySwitch.h"
     43#include "DisallowMacroScratchRegisterUsage.h"
    4344#include "ScratchRegisterAllocator.h"
    4445#include "VirtualRegister.h"
     
    823824        clobbers.set(pinnedRegs->baseMemoryPointer);
    824825        clobbers.set(pinnedRegs->sizeRegister);
     826        if (!isARM64())
     827            clobbers.set(RegisterSet::macroScratchRegisters());
    825828
    826829        auto* patchpoint = addPatchpoint(B3::Void);
     
    830833        patchpoint->effects = effects;
    831834        patchpoint->clobber(clobbers);
     835        patchpoint->numGPScratchRegisters = Gigacage::isEnabled(Gigacage::Primitive) ? 1 : 0;
    832836
    833837        patchpoint->setGenerator([pinnedRegs] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     838            RELEASE_ASSERT(!Gigacage::isEnabled(Gigacage::Primitive) || !isARM64());
     839            AllowMacroScratchRegisterUsageIf allowScratch(jit, !isARM64());
     840            GPRReg baseMemory = pinnedRegs->baseMemoryPointer;
     841            GPRReg scratchOrSize = Gigacage::isEnabled(Gigacage::Primitive) ? params.gpScratch(0) : pinnedRegs->sizeRegister;
     842
    834843            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemorySize()), pinnedRegs->sizeRegister);
    835             jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemory()), pinnedRegs->baseMemoryPointer);
    836 #if CPU(ARM64E)
    837             jit.untagArrayPtr(pinnedRegs->sizeRegister, pinnedRegs->baseMemoryPointer);
    838 #endif
     844            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemory()), baseMemory);
     845
     846            jit.cageConditionally(Gigacage::Primitive, baseMemory, scratchOrSize);
    839847        });
    840848
     
    18451853        patchpoint->clobber(PinnedRegisterInfo::get().toSave(MemoryMode::BoundsChecking));
    18461854        patchpoint->clobber(RegisterSet::macroScratchRegisters());
     1855        patchpoint->numGPScratchRegisters = Gigacage::isEnabled(Gigacage::Primitive) ? 1 : 0;
     1856
    18471857        patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    18481858            AllowMacroScratchRegisterUsage allowScratch(jit);
     
    18581868            //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
    18591869            ASSERT(pinnedRegs.sizeRegister != newContextInstance);
     1870            GPRReg scratchOrSize = Gigacage::isEnabled(Gigacage::Primitive) ? params.gpScratch(0) : pinnedRegs.sizeRegister;
     1871
    18601872            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister); // Memory size.
    18611873            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
    1862 #if CPU(ARM64E)
    1863             jit.untagArrayPtr(pinnedRegs.sizeRegister, baseMemory);
    1864 #endif
     1874
     1875            jit.cageConditionally(Gigacage::Primitive, baseMemory, scratchOrSize);
    18651876        });
    18661877
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

    r245064 r245432  
    4848#include "B3WasmAddressValue.h"
    4949#include "B3WasmBoundsCheckValue.h"
     50#include "DisallowMacroScratchRegisterUsage.h"
    5051#include "JSCInlines.h"
    5152#include "ScratchRegisterAllocator.h"
     
    469470        clobbers.set(pinnedRegs->baseMemoryPointer);
    470471        clobbers.set(pinnedRegs->sizeRegister);
     472        if (!isARM64())
     473            clobbers.set(RegisterSet::macroScratchRegisters());
    471474
    472475        B3::PatchpointValue* patchpoint = block->appendNew<B3::PatchpointValue>(proc, B3::Void, origin());
     
    476479        patchpoint->effects = effects;
    477480        patchpoint->clobber(clobbers);
     481        patchpoint->numGPScratchRegisters = Gigacage::isEnabled(Gigacage::Primitive) ? 1 : 0;
    478482
    479483        patchpoint->append(instance, ValueRep::SomeRegister);
    480 
    481484        patchpoint->setGenerator([pinnedRegs] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
     485            RELEASE_ASSERT(!Gigacage::isEnabled(Gigacage::Primitive) || !isARM64());
     486            AllowMacroScratchRegisterUsageIf allowScratch(jit, !isARM64());
    482487            GPRReg baseMemory = pinnedRegs->baseMemoryPointer;
     488            GPRReg scratchOrSize = Gigacage::isEnabled(Gigacage::Primitive) ? params.gpScratch(0) : pinnedRegs->sizeRegister;
     489
    483490            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemorySize()), pinnedRegs->sizeRegister);
    484491            jit.loadPtr(CCallHelpers::Address(params[0].gpr(), Instance::offsetOfCachedMemory()), baseMemory);
    485 #if CPU(ARM64E)
    486             jit.untagArrayPtr(pinnedRegs->sizeRegister, baseMemory);
    487 #endif
     492
     493            jit.cageConditionally(Gigacage::Primitive, baseMemory, scratchOrSize);
    488494        });
    489495    }
     
    12731279        patchpoint->append(newContextInstance, ValueRep::SomeRegister);
    12741280        patchpoint->append(instanceValue(), ValueRep::SomeRegister);
     1281        patchpoint->numGPScratchRegisters = Gigacage::isEnabled(Gigacage::Primitive) ? 1 : 0;
     1282
    12751283        patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
    12761284            AllowMacroScratchRegisterUsage allowScratch(jit);
     
    12871295            //   see: https://bugs.webkit.org/show_bug.cgi?id=162952
    12881296            ASSERT(pinnedRegs.sizeRegister != newContextInstance);
     1297            GPRReg scratchOrSize = Gigacage::isEnabled(Gigacage::Primitive) ? params.gpScratch(0) : pinnedRegs.sizeRegister;
     1298
    12891299            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister); // Memory size.
    12901300            jit.loadPtr(CCallHelpers::Address(newContextInstance, Instance::offsetOfCachedMemory()), baseMemory); // Memory::void*.
    1291 #if CPU(ARM64E)
    1292             jit.untagArrayPtr(pinnedRegs.sizeRegister, baseMemory);
    1293 #endif
     1301
     1302            jit.cageConditionally(Gigacage::Primitive, baseMemory, scratchOrSize);
    12941303        });
    12951304        doContextSwitch->appendNewControlValue(m_proc, Jump, origin(), continuation);
  • trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp

    r245064 r245432  
    4646    JIT jit;
    4747
    48     GPRReg scratch = GPRInfo::nonPreservedNonArgumentGPR0;
     48    GPRReg scratch = wasmCallingConventionAir().prologueScratch(0);
    4949    GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
    5050    ASSERT(baseMemory != scratch);
     
    6666    // FIXME the following code assumes that all Wasm::Instance have the same pinned registers. https://bugs.webkit.org/show_bug.cgi?id=162952
    6767    // Set up the callee's baseMemory register as well as the memory size registers.
    68     jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister); // Memory size.
    69     jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemory()), baseMemory); // Wasm::Memory::TaggedArrayStoragePtr<void> (void*).
    70 #if CPU(ARM64E)
    71     jit.untagArrayPtr(pinnedRegs.sizeRegister, baseMemory);
    72 #endif
     68    {
     69        GPRReg scratchOrSize = isARM64E() ? pinnedRegs.sizeRegister : wasmCallingConventionAir().prologueScratch(1);
     70
     71        jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister); // Memory size.
     72        jit.loadPtr(JIT::Address(baseMemory, Wasm::Instance::offsetOfCachedMemory()), baseMemory); // Wasm::Memory::TaggedArrayStoragePtr<void> (void*).
     73        jit.cageConditionally(Gigacage::Primitive, baseMemory, scratchOrSize);
     74    }
    7375
    7476    // Tail call into the callee WebAssembly function.
  • trunk/Source/JavaScriptCore/wasm/WasmInstance.h

    r245064 r245432  
    6565    Table* table() { return m_table.get(); }
    6666
    67     void* cachedMemory() const { return m_cachedMemory.get(cachedMemorySize()); }
     67    void* cachedMemory() const { return m_cachedMemory.getMayBeNull(cachedMemorySize()); }
    6868    size_t cachedMemorySize() const { return m_cachedMemorySize; }
    6969
     
    7777    {
    7878        if (m_memory != nullptr) {
    79             m_cachedMemory = TaggedArrayStoragePtr<void>(memory()->memory(), memory()->size());
     79            m_cachedMemory = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>(memory()->memory(), memory()->size());
    8080            m_cachedMemorySize = memory()->size();
    8181        }
     
    144144    void* m_owner { nullptr }; // In a JS embedding, this is a JSWebAssemblyInstance*.
    145145    Context* m_context { nullptr };
    146     TaggedArrayStoragePtr<void> m_cachedMemory;
     146    CagedPtr<Gigacage::Primitive, void, tagCagedPtr> m_cachedMemory;
    147147    size_t m_cachedMemorySize { 0 };
    148148    Ref<Module> m_module;
  • trunk/Source/JavaScriptCore/wasm/WasmMemory.cpp

    r245064 r245432  
    424424        if (m_memory)
    425425            Gigacage::freeVirtualPages(Gigacage::Primitive, memory(), m_size);
    426         m_memory = TaggedArrayStoragePtr<void>(newMemory, desiredSize);
     426        m_memory = CagedMemory(newMemory, desiredSize);
    427427        m_mappedCapacity = desiredSize;
    428428        m_size = desiredSize;
     
    440440            RELEASE_ASSERT_NOT_REACHED();
    441441        }
    442         m_memory.resize(m_size, desiredSize);
     442        m_memory.recage(m_size, desiredSize);
    443443        m_size = desiredSize;
    444444        return success();
  • trunk/Source/JavaScriptCore/wasm/WasmMemory.h

    r245064 r245432  
    3131#include "WasmPageCount.h"
    3232
     33#include <wtf/CagedPtr.h>
    3334#include <wtf/Expected.h>
    3435#include <wtf/Function.h>
    3536#include <wtf/RefCounted.h>
    3637#include <wtf/RefPtr.h>
    37 #include <wtf/TaggedArrayStoragePtr.h>
    3838#include <wtf/Vector.h>
    3939#include <wtf/WeakPtr.h>
     
    7070    static bool addressIsInActiveFastMemory(void*);
    7171
    72     void* memory() const { ASSERT(m_memory.get(size()) == m_memory.getUnsafe()); return m_memory.get(size()); }
     72    void* memory() const { ASSERT(m_memory.getMayBeNull(size()) == m_memory.getUnsafe()); return m_memory.getMayBeNull(size()); }
    7373    size_t size() const { return m_size; }
    7474    PageCount sizeInPages() const { return PageCount::fromBytes(m_size); }
     
    9898    Memory(PageCount initial, PageCount maximum, WTF::Function<void(NotifyPressure)>&& notifyMemoryPressure, WTF::Function<void(SyncTryToReclaim)>&& syncTryToReclaimMemory, WTF::Function<void(GrowSuccess, PageCount, PageCount)>&& growSuccessCallback);
    9999
    100     TaggedArrayStoragePtr<void> m_memory;
     100    using CagedMemory = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>;
     101    CagedMemory m_memory;
    101102    size_t m_size { 0 };
    102103    PageCount m_initial;
  • trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp

    r245064 r245432  
    211211    if (!!info.memory) {
    212212        GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
     213        GPRReg scratchOrSize = wasmCallingConventionAir().prologueScratch(0);
    213214
    214215        if (Context::useFastTLS())
     
    216217
    217218        GPRReg currentInstanceGPR = Context::useFastTLS() ? baseMemory : wasmContextInstanceGPR;
    218         if (mode != MemoryMode::Signaling) {
    219             jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister);
    220             jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
    221 #if CPU(ARM64E)
    222             jit.untagArrayPtr(pinnedRegs.sizeRegister, baseMemory);
    223 #endif
     219        if (isARM64E()) {
     220            if (mode != Wasm::MemoryMode::Signaling)
     221                scratchOrSize = pinnedRegs.sizeRegister;
     222            jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemorySize()), scratchOrSize);
    224223        } else {
    225 #if CPU(ARM64E)
    226             GPRReg scratch = wasmCallingConventionAir().prologueScratch(0);
    227 
    228             jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemorySize()), scratch);
    229             jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
    230             jit.untagArrayPtr(scratch, baseMemory);
    231 #else
    232             jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
    233 #endif
    234         }
     224            if (mode != Wasm::MemoryMode::Signaling)
     225                jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister);
     226        }
     227
     228        jit.loadPtr(CCallHelpers::Address(currentInstanceGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
     229        jit.cageConditionally(Gigacage::Primitive, baseMemory, scratchOrSize);
    235230    }
    236231
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp

    r245251 r245432  
    396396    if (!!moduleInformation.memory) {
    397397        GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
    398 
    399         if (instance()->memoryMode() != Wasm::MemoryMode::Signaling) {
    400             jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister);
    401             jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
    402 #if CPU(ARM64E)
    403             jit.untagArrayPtr(pinnedRegs.sizeRegister, baseMemory);
    404 #endif
     398        GPRReg scratchOrSize = scratch2GPR;
     399        auto mode = instance()->memoryMode();
     400
     401        if (isARM64E()) {
     402            if (mode != Wasm::MemoryMode::Signaling)
     403                scratchOrSize = pinnedRegs.sizeRegister;
     404            jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemorySize()), scratchOrSize);
    405405        } else {
    406 #if CPU(ARM64E)
    407             jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemorySize()), scratch2GPR);
    408             jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
    409             jit.untagArrayPtr(scratch2GPR, baseMemory);
    410 #else
    411             jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
    412 #endif
     406            if (mode != Wasm::MemoryMode::Signaling)
     407                jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemorySize()), pinnedRegs.sizeRegister);
    413408        }
     409
     410        jit.loadPtr(CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedMemory()), baseMemory);
     411        jit.cageConditionally(Gigacage::Primitive, baseMemory, scratchOrSize);
    414412    }
    415413
  • trunk/Source/WTF/ChangeLog

    r245418 r245432  
     12019-05-16  Keith Miller  <keith_miller@apple.com>
     2
     3        Wasm should cage the memory base pointers in structs
     4        https://bugs.webkit.org/show_bug.cgi?id=197620
     5
     6        Reviewed by Saam Barati.
     7
     8        Rename reauthenticate to recage.
     9
     10        * wtf/CagedPtr.h:
     11        (WTF::CagedPtr::recage):
     12        (WTF::CagedPtr::reauthenticate): Deleted.
     13
    1142019-05-16  Alex Christensen  <achristensen@webkit.org>
    215
  • trunk/Source/WTF/wtf/CagedPtr.h

    r245064 r245432  
    7979    /* T& */ at(unsigned index, unsigned size) const { return get(size)[index]; }
    8080
    81     void reauthenticate(unsigned oldSize, unsigned newSize)
     81    void recage(unsigned oldSize, unsigned newSize)
    8282    {
    8383        auto ptr = get(oldSize);
  • trunk/Source/bmalloc/ChangeLog

    r245064 r245432  
     12019-05-16  Keith Miller  <keith_miller@apple.com>
     2
     3        Wasm should cage the memory base pointers in structs
     4        https://bugs.webkit.org/show_bug.cgi?id=197620
     5
     6        Reviewed by Saam Barati.
     7
     8        Fix signature to take Gigacage::Kind, which matches GIGACAGE_ENABLED build.
     9
     10        * bmalloc/Gigacage.h:
     11        (Gigacage::isEnabled):
     12
    1132019-05-08  Keith Miller  <keith_miller@apple.com>
    214
  • trunk/Source/bmalloc/bmalloc/Gigacage.h

    r245064 r245432  
    227227BINLINE bool wasEnabled() { return false; }
    228228BINLINE bool isCaged(Kind, const void*) { return true; }
    229 BINLINE bool isEnabled() { return false; }
     229BINLINE bool isEnabled(Kind) { return false; }
    230230template<typename T> BINLINE T* caged(Kind, T* ptr) { return ptr; }
    231231template<typename T> BINLINE T* cagedMayBeNull(Kind, T* ptr) { return ptr; }
Note: See TracChangeset for help on using the changeset viewer.