Changeset 229518 in webkit


Ignore:
Timestamp:
Mar 11, 2018 2:09:20 PM (6 years ago)
Author:
fpizlo@apple.com
Message:

Split DirectArguments into JSValueOOB and JSValueStrict parts
https://bugs.webkit.org/show_bug.cgi?id=183458

Reviewed by Yusuke Suzuki.
Source/JavaScriptCore:


Our Spectre plan for JSValue objects is to allow inline JSValue stores and loads guarded by
unmitigated structure checks. This works because objects reachable from JSValues (i.e. JSValue
objects, like String, Symbol, and any descendant of JSObject) will only contain fields that it's OK
to read and write within a Spectre mitigation window. Writes are important, because within the
window, a write could appear to be made speculatively and rolled out later. This means that:

  • JSValue objects cannot have lengths, masks, or anything else inline.


  • JSValue objects cannot have an inline type that is used as part of a Spectre mitigation for a type check, unless that type is in the form of a poison key.


This means that the dynamic poisoning that I previously landed for DirectArguments is wrong. It also
means that it's wrong for DirectArguments to have an inline length.

This changes DirectArguments to use poisoning according to the universal formula:

  • The random accessed portions are out-of-line, pointed to by a poisoned pointer.


  • No inline length.


Surprisingly, this is perf-neutral. It's probably perf-neutral because our compiler optimizations
amortize whatever cost there was.

  • bytecode/AccessCase.cpp:

(JSC::AccessCase::generateWithGuard):

  • dfg/DFGCallCreateDirectArgumentsSlowPathGenerator.h:

(JSC::DFG::CallCreateDirectArgumentsSlowPathGenerator::CallCreateDirectArgumentsSlowPathGenerator):

  • dfg/DFGCallCreateDirectArgumentsWithKnownLengthSlowPathGenerator.h: Added.

(JSC::DFG::CallCreateDirectArgumentsWithKnownLengthSlowPathGenerator::CallCreateDirectArgumentsWithKnownLengthSlowPathGenerator):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileGetByValOnDirectArguments):
(JSC::DFG::SpeculativeJIT::compileGetArrayLength):
(JSC::DFG::SpeculativeJIT::compileCreateDirectArguments):
(JSC::DFG::SpeculativeJIT::compileGetFromArguments):
(JSC::DFG::SpeculativeJIT::compilePutToArguments):

  • ftl/FTLAbstractHeapRepository.h:
  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength):
(JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateDirectArguments):
(JSC::FTL::DFG::LowerDFGToB3::compileGetFromArguments):
(JSC::FTL::DFG::LowerDFGToB3::compilePutToArguments):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckSubClass):
(JSC::FTL::DFG::LowerDFGToB3::allocateVariableSizedHeapCell):
(JSC::FTL::DFG::LowerDFGToB3::dynamicPoison): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::dynamicPoisonOnLoadedType): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::dynamicPoisonOnType): Deleted.

  • heap/SecurityKind.h:
  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_get_from_arguments):
(JSC::JIT::emit_op_put_to_arguments):
(JSC::JIT::emitDirectArgumentsGetByVal):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emit_op_get_from_arguments):
(JSC::JIT::emit_op_put_to_arguments):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/DirectArguments.cpp:

(JSC::DirectArguments::DirectArguments):
(JSC::DirectArguments::createUninitialized):
(JSC::DirectArguments::create):
(JSC::DirectArguments::createByCopying):
(JSC::DirectArguments::estimatedSize):
(JSC::DirectArguments::visitChildren):
(JSC::DirectArguments::overrideThings):
(JSC::DirectArguments::copyToArguments):
(JSC::DirectArguments::mappedArgumentsSize):

  • runtime/DirectArguments.h:
  • runtime/JSCPoison.h:
  • runtime/JSLexicalEnvironment.h:
  • runtime/JSSymbolTableObject.h:
  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

Source/WTF:

  • wtf/MathExtras.h:

(WTF::dynamicPoison): Deleted.

Location:
trunk/Source
Files:
1 added
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r229517 r229518  
     12018-03-09  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Split DirectArguments into JSValueOOB and JSValueStrict parts
     4        https://bugs.webkit.org/show_bug.cgi?id=183458
     5
     6        Reviewed by Yusuke Suzuki.
     7       
     8        Our Spectre plan for JSValue objects is to allow inline JSValue stores and loads guarded by
     9        unmitigated structure checks. This works because objects reachable from JSValues (i.e. JSValue
     10        objects, like String, Symbol, and any descendant of JSObject) will only contain fields that it's OK
     11        to read and write within a Spectre mitigation window. Writes are important, because within the
     12        window, a write could appear to be made speculatively and rolled out later. This means that:
     13       
     14        - JSValue objects cannot have lengths, masks, or anything else inline.
     15       
     16        - JSValue objects cannot have an inline type that is used as part of a Spectre mitigation for a type
     17          check, unless that type is in the form of a poison key.
     18       
     19        This means that the dynamic poisoning that I previously landed for DirectArguments is wrong. It also
     20        means that it's wrong for DirectArguments to have an inline length.
     21       
     22        This changes DirectArguments to use poisoning according to the universal formula:
     23       
     24        - The random accessed portions are out-of-line, pointed to by a poisoned pointer.
     25       
     26        - No inline length.
     27       
     28        Surprisingly, this is perf-neutral. It's probably perf-neutral because our compiler optimizations
     29        amortize whatever cost there was.
     30
     31        * bytecode/AccessCase.cpp:
     32        (JSC::AccessCase::generateWithGuard):
     33        * dfg/DFGCallCreateDirectArgumentsSlowPathGenerator.h:
     34        (JSC::DFG::CallCreateDirectArgumentsSlowPathGenerator::CallCreateDirectArgumentsSlowPathGenerator):
     35        * dfg/DFGCallCreateDirectArgumentsWithKnownLengthSlowPathGenerator.h: Added.
     36        (JSC::DFG::CallCreateDirectArgumentsWithKnownLengthSlowPathGenerator::CallCreateDirectArgumentsWithKnownLengthSlowPathGenerator):
     37        * dfg/DFGSpeculativeJIT.cpp:
     38        (JSC::DFG::SpeculativeJIT::compileGetByValOnDirectArguments):
     39        (JSC::DFG::SpeculativeJIT::compileGetArrayLength):
     40        (JSC::DFG::SpeculativeJIT::compileCreateDirectArguments):
     41        (JSC::DFG::SpeculativeJIT::compileGetFromArguments):
     42        (JSC::DFG::SpeculativeJIT::compilePutToArguments):
     43        * ftl/FTLAbstractHeapRepository.h:
     44        * ftl/FTLLowerDFGToB3.cpp:
     45        (JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength):
     46        (JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
     47        (JSC::FTL::DFG::LowerDFGToB3::compileCreateDirectArguments):
     48        (JSC::FTL::DFG::LowerDFGToB3::compileGetFromArguments):
     49        (JSC::FTL::DFG::LowerDFGToB3::compilePutToArguments):
     50        (JSC::FTL::DFG::LowerDFGToB3::compileCheckSubClass):
     51        (JSC::FTL::DFG::LowerDFGToB3::allocateVariableSizedHeapCell):
     52        (JSC::FTL::DFG::LowerDFGToB3::dynamicPoison): Deleted.
     53        (JSC::FTL::DFG::LowerDFGToB3::dynamicPoisonOnLoadedType): Deleted.
     54        (JSC::FTL::DFG::LowerDFGToB3::dynamicPoisonOnType): Deleted.
     55        * heap/SecurityKind.h:
     56        * jit/JITPropertyAccess.cpp:
     57        (JSC::JIT::emit_op_get_from_arguments):
     58        (JSC::JIT::emit_op_put_to_arguments):
     59        (JSC::JIT::emitDirectArgumentsGetByVal):
     60        * jit/JITPropertyAccess32_64.cpp:
     61        (JSC::JIT::emit_op_get_from_arguments):
     62        (JSC::JIT::emit_op_put_to_arguments):
     63        * llint/LowLevelInterpreter.asm:
     64        * llint/LowLevelInterpreter32_64.asm:
     65        * llint/LowLevelInterpreter64.asm:
     66        * runtime/DirectArguments.cpp:
     67        (JSC::DirectArguments::DirectArguments):
     68        (JSC::DirectArguments::createUninitialized):
     69        (JSC::DirectArguments::create):
     70        (JSC::DirectArguments::createByCopying):
     71        (JSC::DirectArguments::estimatedSize):
     72        (JSC::DirectArguments::visitChildren):
     73        (JSC::DirectArguments::overrideThings):
     74        (JSC::DirectArguments::copyToArguments):
     75        (JSC::DirectArguments::mappedArgumentsSize):
     76        * runtime/DirectArguments.h:
     77        * runtime/JSCPoison.h:
     78        * runtime/JSLexicalEnvironment.h:
     79        * runtime/JSSymbolTableObject.h:
     80        * runtime/VM.cpp:
     81        (JSC::VM::VM):
     82        * runtime/VM.h:
     83
    1842018-03-11  Yusuke Suzuki  <utatane.tea@gmail.com>
    285
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r229481 r229518  
    162162                0F25F1B2181635F300522F39 /* FTLSlowPathCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F25F1AB181635F300522F39 /* FTLSlowPathCall.h */; settings = {ATTRIBUTES = (Private, ); }; };
    163163                0F25F1B4181635F300522F39 /* FTLSlowPathCallKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F25F1AD181635F300522F39 /* FTLSlowPathCallKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
     164                0F26A7A32053895C0090A141 /* DFGCallCreateDirectArgumentsWithKnownLengthSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F26A7A2205389580090A141 /* DFGCallCreateDirectArgumentsWithKnownLengthSlowPathGenerator.h */; };
    164165                0F2AC5671E8A0B790001EE3F /* AirFixSpillsAfterTerminals.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2AC5651E8A0B760001EE3F /* AirFixSpillsAfterTerminals.h */; };
    165166                0F2AC56B1E8A0BD50001EE3F /* AirAllocateRegistersAndStackByLinearScan.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2AC5691E8A0BD10001EE3F /* AirAllocateRegistersAndStackByLinearScan.h */; };
     
    20602061                0F25F1AC181635F300522F39 /* FTLSlowPathCallKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLSlowPathCallKey.cpp; path = ftl/FTLSlowPathCallKey.cpp; sourceTree = "<group>"; };
    20612062                0F25F1AD181635F300522F39 /* FTLSlowPathCallKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSlowPathCallKey.h; path = ftl/FTLSlowPathCallKey.h; sourceTree = "<group>"; };
     2063                0F26A7A2205389580090A141 /* DFGCallCreateDirectArgumentsWithKnownLengthSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCallCreateDirectArgumentsWithKnownLengthSlowPathGenerator.h; path = dfg/DFGCallCreateDirectArgumentsWithKnownLengthSlowPathGenerator.h; sourceTree = "<group>"; };
    20622064                0F275F2C1ECE079600620D47 /* Intrinsic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Intrinsic.cpp; sourceTree = "<group>"; };
    20632065                0F2AC5641E8A0B760001EE3F /* AirFixSpillsAfterTerminals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirFixSpillsAfterTerminals.cpp; path = b3/air/AirFixSpillsAfterTerminals.cpp; sourceTree = "<group>"; };
     
    71347136                                0F256C341627B0AA007F2783 /* DFGCallArrayAllocatorSlowPathGenerator.h */,
    71357137                                0FBDB9AC1AB0FBC6000B57E5 /* DFGCallCreateDirectArgumentsSlowPathGenerator.h */,
     7138                                0F26A7A2205389580090A141 /* DFGCallCreateDirectArgumentsWithKnownLengthSlowPathGenerator.h */,
    71367139                                0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */,
    71377140                                0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */,
     
    87478750                                52B310FB1974AE610080857C /* FunctionHasExecutedCache.h in Headers */,
    87488751                                FE4BFF2C1AD476E700088F87 /* FunctionOverrides.h in Headers */,
     8752                                0F26A7A32053895C0090A141 /* DFGCallCreateDirectArgumentsWithKnownLengthSlowPathGenerator.h in Headers */,
    87498753                                BC18C4050E16F5CD00B34460 /* FunctionPrototype.h in Headers */,
    87508754                                62D2D3901ADF103F000206C1 /* FunctionRareData.h in Headers */,
  • trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp

    r229391 r229518  
    384384                CCallHelpers::NonZero,
    385385                CCallHelpers::Address(baseGPR, DirectArguments::offsetOfMappedArguments())));
     386        jit.loadPtr(
     387            CCallHelpers::Address(baseGPR, DirectArguments::offsetOfStorage()),
     388            valueRegs.payloadGPR());
     389        jit.xorPtr(CCallHelpers::TrustedImmPtr(DirectArgumentsPoison::key()), valueRegs.payloadGPR());
    386390        jit.load32(
    387             CCallHelpers::Address(baseGPR, DirectArguments::offsetOfLength()),
     391            CCallHelpers::Address(valueRegs.payloadGPR(), DirectArguments::offsetOfLengthInStorage()),
    388392            valueRegs.payloadGPR());
    389393        jit.boxInt32(valueRegs.payloadGPR(), valueRegs);
  • trunk/Source/JavaScriptCore/dfg/DFGCallCreateDirectArgumentsSlowPathGenerator.h

    r218794 r229518  
    11/*
    2  * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3535namespace JSC { namespace DFG {
    3636
    37 // This calls operationCreateDirectArguments but then restores the value of lengthGPR.
     37// This calls operationCreateDirectArguments but then restores the value of lengthGPR and storageGPR.
    3838class CallCreateDirectArgumentsSlowPathGenerator : public JumpingSlowPathGenerator<MacroAssembler::JumpList> {
    3939public:
    4040    CallCreateDirectArgumentsSlowPathGenerator(
    4141        MacroAssembler::JumpList from, SpeculativeJIT* jit, GPRReg resultGPR, RegisteredStructure structure,
    42         GPRReg lengthGPR, unsigned minCapacity)
     42        GPRReg lengthGPR, GPRReg storageGPR, unsigned minCapacity)
    4343        : JumpingSlowPathGenerator<MacroAssembler::JumpList>(from, jit)
    4444        , m_resultGPR(resultGPR)
    4545        , m_structure(structure)
    4646        , m_lengthGPR(lengthGPR)
     47        , m_storageGPR(storageGPR)
    4748        , m_minCapacity(minCapacity)
    4849    {
     
    6263        jit->m_jit.exceptionCheck();
    6364        jit->m_jit.loadPtr(
    64             MacroAssembler::Address(m_resultGPR, DirectArguments::offsetOfLength()), m_lengthGPR);
     65            MacroAssembler::Address(m_resultGPR, DirectArguments::offsetOfStorage()), m_storageGPR);
     66        jit->m_jit.xorPtr(
     67            MacroAssembler::TrustedImmPtr(DirectArgumentsPoison::key()), m_storageGPR);
     68        jit->m_jit.load32(
     69            MacroAssembler::Address(m_storageGPR, DirectArguments::offsetOfLengthInStorage()), m_lengthGPR);
    6570        jumpTo(jit);
    6671    }
     
    7075    RegisteredStructure m_structure;
    7176    GPRReg m_lengthGPR;
     77    GPRReg m_storageGPR;
    7278    unsigned m_minCapacity;
    7379    Vector<SilentRegisterSavePlan, 2> m_plans;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r229514 r229518  
    3434#include "DFGCallArrayAllocatorSlowPathGenerator.h"
    3535#include "DFGCallCreateDirectArgumentsSlowPathGenerator.h"
     36#include "DFGCallCreateDirectArgumentsWithKnownLengthSlowPathGenerator.h"
    3637#include "DFGCapabilities.h"
    3738#include "DFGMayExit.h"
     
    64266427#endif
    64276428    GPRTemporary scratch(this);
     6429    GPRTemporary storage(this);
    64286430   
    64296431    GPRReg baseReg = base.gpr();
     
    64376439#endif
    64386440    GPRReg scratchReg = scratch.gpr();
     6441    GPRReg storageReg = storage.gpr();
    64396442   
    64406443    if (!m_compileOkay)
     
    64486451            MacroAssembler::NonZero,
    64496452            MacroAssembler::Address(baseReg, DirectArguments::offsetOfMappedArguments())));
    6450 
    6451     m_jit.load32(CCallHelpers::Address(baseReg, DirectArguments::offsetOfLength()), scratchReg);
     6453   
     6454    m_jit.loadPtr(CCallHelpers::Address(baseReg, DirectArguments::offsetOfStorage()), storageReg);
     6455    m_jit.xorPtr(TrustedImmPtr(DirectArgumentsPoison::key()), storageReg);
     6456   
     6457    m_jit.load32(CCallHelpers::Address(storageReg, DirectArguments::offsetOfLengthInStorage()), scratchReg);
    64526458    auto isOutOfBounds = m_jit.branch32(CCallHelpers::AboveOrEqual, propertyReg, scratchReg);
    64536459    if (node->arrayMode().isInBounds())
    64546460        speculationCheck(OutOfBounds, JSValueSource(), 0, isOutOfBounds);
    64556461   
    6456     m_jit.emitDynamicPoisonOnType(baseReg, resultReg, DirectArgumentsType);
    64576462    m_jit.emitPreparePreciseIndexMask32(propertyReg, scratchReg, scratchReg);
    64586463
    64596464    m_jit.loadValue(
    64606465        MacroAssembler::BaseIndex(
    6461             baseReg, propertyReg, MacroAssembler::TimesEight, DirectArguments::storageOffset()),
     6466            storageReg, propertyReg, MacroAssembler::TimesEight),
    64626467        resultRegs);
    64636468   
     
    66446649                MacroAssembler::Address(baseReg, DirectArguments::offsetOfMappedArguments())));
    66456650       
     6651        m_jit.loadPtr(
     6652            MacroAssembler::Address(baseReg, DirectArguments::offsetOfStorage()), resultReg);
     6653        m_jit.xorPtr(
     6654            TrustedImmPtr(DirectArgumentsPoison::key()), resultReg);
    66466655        m_jit.load32(
    6647             MacroAssembler::Address(baseReg, DirectArguments::offsetOfLength()), resultReg);
     6656            MacroAssembler::Address(resultReg, DirectArguments::offsetOfLengthInStorage()), resultReg);
    66486657       
    66496658        int32Result(resultReg, node);
     
    69686977void SpeculativeJIT::compileCreateDirectArguments(Node* node)
    69696978{
    6970     // FIXME: A more effective way of dealing with the argument count and callee is to have
    6971     // them be explicit arguments to this node.
    6972     // https://bugs.webkit.org/show_bug.cgi?id=142207
    6973    
    6974     GPRTemporary result(this);
    6975     GPRTemporary scratch1(this);
    6976     GPRTemporary scratch2(this);
    6977     GPRTemporary length;
    6978     GPRReg resultGPR = result.gpr();
    6979     GPRReg scratch1GPR = scratch1.gpr();
    6980     GPRReg scratch2GPR = scratch2.gpr();
    6981     GPRReg lengthGPR = InvalidGPRReg;
    6982     JSValueRegs valueRegs = JSValueRegs::withTwoAvailableRegs(scratch1GPR, scratch2GPR);
    6983        
     6979    VM& vm = *m_jit.vm();
     6980   
     6981    bool lengthIsKnown = node->origin.semantic.inlineCallFrame
     6982        && !node->origin.semantic.inlineCallFrame->isVarargs();
     6983    unsigned knownLength = UINT_MAX;
     6984   
     6985    RegisteredStructure structure =
     6986        m_jit.graph().registerStructure(m_jit.graph().globalObjectFor(node->origin.semantic)->directArgumentsStructure());
    69846987    unsigned minCapacity = m_jit.graph().baselineCodeBlockFor(node->origin.semantic)->numParameters() - 1;
    6985        
    6986     unsigned knownLength;
    6987     bool lengthIsKnown; // if false, lengthGPR will have the length.
    6988     if (node->origin.semantic.inlineCallFrame
    6989         && !node->origin.semantic.inlineCallFrame->isVarargs()) {
    6990         knownLength = node->origin.semantic.inlineCallFrame->argumentCountIncludingThis - 1;
    6991         lengthIsKnown = true;
    6992     } else {
    6993         knownLength = UINT_MAX;
    6994         lengthIsKnown = false;
    6995            
    6996         GPRTemporary realLength(this);
    6997         length.adopt(realLength);
    6998         lengthGPR = length.gpr();
    6999 
     6988   
     6989    GPRReg resultGPR;
     6990    GPRReg lengthGPR;
     6991    GPRReg scratch1GPR;
     6992    GPRReg scratch2GPR;
     6993    GPRReg storageGPR;
     6994    JSValueRegs valueRegs;
     6995   
     6996    auto loadLength = [&] () {
    70006997        VirtualRegister argumentCountRegister = m_jit.argumentCount(node->origin.semantic);
    70016998        m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), lengthGPR);
    70026999        m_jit.sub32(TrustedImm32(1), lengthGPR);
    7003     }
    7004        
    7005     RegisteredStructure structure =
    7006         m_jit.graph().registerStructure(m_jit.graph().globalObjectFor(node->origin.semantic)->directArgumentsStructure());
    7007        
    7008     // Use a different strategy for allocating the object depending on whether we know its
    7009     // size statically.
    7010     JITCompiler::JumpList slowPath;
    7011     if (lengthIsKnown) {
     7000    };
     7001       
     7002    GPRTemporary result;
     7003    GPRTemporary scratch1;
     7004    GPRTemporary scratch2;
     7005    GPRTemporary storage;
     7006    GPRTemporary length;
     7007
     7008    if (isX86() && is32Bit() && !lengthIsKnown) {
     7009        GPRFlushedCallResult result(this);
     7010        resultGPR = result.gpr();
     7011        RELEASE_ASSERT(resultGPR == GPRInfo::regT0);
     7012        flushRegisters();
     7013        lengthGPR = GPRInfo::regT1; // Can be anything we like because registers are flushed.
     7014        scratch1GPR = GPRInfo::regT2;
     7015        scratch2GPR = GPRInfo::regT3;
     7016        storageGPR = GPRInfo::regT4;
     7017        valueRegs = JSValueRegs::withTwoAvailableRegs(scratch1GPR, scratch2GPR);
     7018        loadLength();
     7019        callOperation(operationCreateDirectArguments, resultGPR, structure, lengthGPR, minCapacity);
     7020        m_jit.exceptionCheck();
     7021        m_jit.loadPtr(MacroAssembler::Address(resultGPR, DirectArguments::offsetOfStorage()), storageGPR);
     7022        m_jit.xorPtr(TrustedImmPtr(DirectArgumentsPoison::key()), storageGPR);
     7023        m_jit.load32(MacroAssembler::Address(storageGPR, DirectArguments::offsetOfLengthInStorage()), lengthGPR);
     7024    } else {
     7025        // FIXME: A more effective way of dealing with the argument count and callee is to have
     7026        // them be explicit arguments to this node.
     7027        // https://bugs.webkit.org/show_bug.cgi?id=142207
     7028   
     7029        GPRTemporary realResult(this);
     7030        result.adopt(realResult);
     7031        GPRTemporary realScratch1(this);
     7032        scratch1.adopt(realScratch1);
     7033        GPRTemporary realScratch2(this);
     7034        scratch2.adopt(realScratch2);
     7035        GPRTemporary realStorage(this);
     7036        storage.adopt(realStorage);
     7037        resultGPR = result.gpr();
     7038        scratch1GPR = scratch1.gpr();
     7039        scratch2GPR = scratch2.gpr();
     7040        lengthGPR = InvalidGPRReg;
     7041        storageGPR = storage.gpr();
     7042        valueRegs = JSValueRegs::withTwoAvailableRegs(scratch1GPR, scratch2GPR);
     7043       
     7044        if (lengthIsKnown)
     7045            knownLength = node->origin.semantic.inlineCallFrame->argumentCountIncludingThis - 1;
     7046        else {
     7047            GPRTemporary realLength(this);
     7048            length.adopt(realLength);
     7049            lengthGPR = length.gpr();
     7050           
     7051            loadLength();
     7052        }
     7053       
     7054        // Use a different strategy for allocating the object depending on whether we know its
     7055        // size statically.
     7056        JITCompiler::JumpList slowPath;
     7057        if (lengthIsKnown) {
     7058            JITAllocator storageAllocator = JITAllocator::constant(
     7059                vm.jsValueGigacageAuxiliarySpace.allocatorForNonVirtual(
     7060                    DirectArguments::storageSize(std::max(knownLength, minCapacity)),
     7061                    AllocatorForMode::AllocatorIfExists));
     7062       
     7063            m_jit.emitAllocate(storageGPR, storageAllocator, scratch1GPR, scratch2GPR, slowPath);
     7064            m_jit.addPtr(TrustedImmPtr(DirectArguments::storageHeaderSize()), storageGPR);
     7065            m_jit.store32(
     7066                TrustedImm32(knownLength),
     7067                JITCompiler::Address(storageGPR, DirectArguments::offsetOfLengthInStorage()));
     7068        } else {
     7069            JITCompiler::Jump tooFewArguments;
     7070            if (minCapacity) {
     7071                tooFewArguments =
     7072                    m_jit.branch32(JITCompiler::Below, lengthGPR, TrustedImm32(minCapacity));
     7073            }
     7074            m_jit.lshift32(lengthGPR, TrustedImm32(3), scratch1GPR);
     7075            m_jit.add32(TrustedImm32(DirectArguments::storageHeaderSize()), scratch1GPR);
     7076            if (minCapacity) {
     7077                JITCompiler::Jump done = m_jit.jump();
     7078                tooFewArguments.link(&m_jit);
     7079                m_jit.move(TrustedImm32(DirectArguments::storageSize(minCapacity)), scratch1GPR);
     7080                done.link(&m_jit);
     7081            }
     7082       
     7083            m_jit.emitAllocateVariableSized(
     7084                storageGPR, vm.jsValueGigacageAuxiliarySpace, scratch1GPR, scratch1GPR, scratch2GPR, slowPath);
     7085            m_jit.addPtr(TrustedImmPtr(DirectArguments::storageHeaderSize()), storageGPR);
     7086            m_jit.store32(
     7087                lengthGPR,
     7088                JITCompiler::Address(storageGPR, DirectArguments::offsetOfLengthInStorage()));
     7089        }
     7090   
     7091        m_jit.store32(
     7092            TrustedImm32(minCapacity),
     7093            JITCompiler::Address(storageGPR, DirectArguments::offsetOfMinCapacityInStorage()));
     7094   
    70127095        auto butterfly = TrustedImmPtr(nullptr);
    70137096        auto mask = TrustedImm32(0);
    7014         emitAllocateJSObjectWithKnownSize<DirectArguments>(
    7015             resultGPR, TrustedImmPtr(structure), butterfly, mask, scratch1GPR, scratch2GPR,
    7016             slowPath, DirectArguments::allocationSize(std::max(knownLength, minCapacity)));
    7017            
    7018         m_jit.store32(
    7019             TrustedImm32(knownLength),
    7020             JITCompiler::Address(resultGPR, DirectArguments::offsetOfLength()));
    7021     } else {
    7022         JITCompiler::Jump tooFewArguments;
    7023         if (minCapacity) {
    7024             tooFewArguments =
    7025                 m_jit.branch32(JITCompiler::Below, lengthGPR, TrustedImm32(minCapacity));
    7026         }
    7027         m_jit.lshift32(lengthGPR, TrustedImm32(3), scratch1GPR);
    7028         m_jit.add32(TrustedImm32(DirectArguments::storageOffset()), scratch1GPR);
    7029         if (minCapacity) {
    7030             JITCompiler::Jump done = m_jit.jump();
    7031             tooFewArguments.link(&m_jit);
    7032             m_jit.move(TrustedImm32(DirectArguments::allocationSize(minCapacity)), scratch1GPR);
    7033             done.link(&m_jit);
    7034         }
    7035        
    7036         emitAllocateVariableSizedJSObject<DirectArguments>(
    7037             resultGPR, TrustedImmPtr(structure), scratch1GPR, scratch1GPR, scratch2GPR,
    7038             slowPath);
    7039            
    7040         m_jit.store32(
    7041             lengthGPR, JITCompiler::Address(resultGPR, DirectArguments::offsetOfLength()));
    7042     }
    7043        
    7044     m_jit.store32(
    7045         TrustedImm32(minCapacity),
    7046         JITCompiler::Address(resultGPR, DirectArguments::offsetOfMinCapacity()));
    7047        
    7048     m_jit.storePtr(
    7049         TrustedImmPtr(nullptr), JITCompiler::Address(resultGPR, DirectArguments::offsetOfMappedArguments()));
    7050 
    7051     m_jit.storePtr(
    7052         TrustedImmPtr(nullptr), JITCompiler::Address(resultGPR, DirectArguments::offsetOfModifiedArgumentsDescriptor()));
    7053    
    7054     if (lengthIsKnown) {
    7055         addSlowPathGenerator(
    7056             slowPathCall(
    7057                 slowPath, this, operationCreateDirectArguments, resultGPR, structure,
    7058                 knownLength, minCapacity));
    7059     } else {
    7060         auto generator = std::make_unique<CallCreateDirectArgumentsSlowPathGenerator>(
    7061             slowPath, this, resultGPR, structure, lengthGPR, minCapacity);
     7097        emitAllocateJSObject<DirectArguments>(resultGPR, TrustedImmPtr(structure), butterfly, mask, scratch1GPR, scratch2GPR, slowPath);
     7098        m_jit.move(storageGPR, scratch1GPR);
     7099        m_jit.xorPtr(TrustedImmPtr(DirectArgumentsPoison::key()), scratch1GPR);
     7100        m_jit.storePtr(scratch1GPR, JITCompiler::Address(resultGPR, DirectArguments::offsetOfStorage()));
     7101       
     7102        m_jit.storePtr(
     7103            TrustedImmPtr(nullptr), JITCompiler::Address(resultGPR, DirectArguments::offsetOfMappedArguments()));
     7104
     7105        m_jit.storePtr(
     7106            TrustedImmPtr(nullptr), JITCompiler::Address(resultGPR, DirectArguments::offsetOfModifiedArgumentsDescriptor()));
     7107   
     7108        std::unique_ptr<SlowPathGenerator> generator;
     7109        if (lengthIsKnown) {
     7110            generator = std::make_unique<CallCreateDirectArgumentsWithKnownLengthSlowPathGenerator>(
     7111                slowPath, this, resultGPR, structure, knownLength, storageGPR, minCapacity);
     7112        } else {
     7113            generator = std::make_unique<CallCreateDirectArgumentsSlowPathGenerator>(
     7114                slowPath, this, resultGPR, structure, lengthGPR, storageGPR, minCapacity);
     7115        }
    70627116        addSlowPathGenerator(WTFMove(generator));
    70637117    }
    7064        
     7118   
    70657119    if (node->origin.semantic.inlineCallFrame) {
    70667120        if (node->origin.semantic.inlineCallFrame->isClosureCall) {
     
    70887142            m_jit.loadValue(JITCompiler::addressFor(start + i), valueRegs);
    70897143            m_jit.storeValue(
    7090                 valueRegs, JITCompiler::Address(resultGPR, DirectArguments::offsetOfSlot(i)));
     7144                valueRegs, JITCompiler::Address(storageGPR, i * sizeof(WriteBarrier<Unknown>)));
    70917145        }
    70927146    } else {
     
    71097163            valueRegs,
    71107164            JITCompiler::BaseIndex(
    7111                 resultGPR, lengthGPR, JITCompiler::TimesEight,
    7112                 DirectArguments::storageOffset()));
     7165                storageGPR, lengthGPR, JITCompiler::TimesEight));
    71137166        m_jit.branchTest32(MacroAssembler::NonZero, lengthGPR).linkTo(loop, &m_jit);
    71147167        if (done.isSet())
    71157168            done.link(&m_jit);
    71167169    }
    7117        
    7118     m_jit.mutatorFence(*m_jit.vm());
     7170   
     7171    m_jit.mutatorFence(vm);
    71197172       
    71207173    cellResult(resultGPR, node);
     
    71297182    JSValueRegs resultRegs = result.regs();
    71307183   
    7131     m_jit.loadValue(JITCompiler::Address(argumentsGPR, DirectArguments::offsetOfSlot(node->capturedArgumentsOffset().offset())), resultRegs);
     7184    m_jit.loadPtr(JITCompiler::Address(argumentsGPR, DirectArguments::offsetOfStorage()), resultRegs.payloadGPR());
     7185    m_jit.xorPtr(TrustedImmPtr(DirectArgumentsPoison::key()), resultRegs.payloadGPR());
     7186    m_jit.loadValue(JITCompiler::Address(resultRegs.payloadGPR(), node->capturedArgumentsOffset().offset() * sizeof(WriteBarrier<Unknown>)), resultRegs);
    71327187    jsValueResult(resultRegs, node);
    71337188}
     
    71377192    SpeculateCellOperand arguments(this, node->child1());
    71387193    JSValueOperand value(this, node->child2());
     7194    GPRTemporary storage(this);
    71397195   
    71407196    GPRReg argumentsGPR = arguments.gpr();
     7197    GPRReg storageGPR = storage.gpr();
    71417198    JSValueRegs valueRegs = value.jsValueRegs();
    71427199   
    7143     m_jit.storeValue(valueRegs, JITCompiler::Address(argumentsGPR, DirectArguments::offsetOfSlot(node->capturedArgumentsOffset().offset())));
     7200    m_jit.loadPtr(JITCompiler::Address(argumentsGPR, DirectArguments::offsetOfStorage()), storageGPR);
     7201    m_jit.xorPtr(TrustedImmPtr(DirectArgumentsPoison::key()), storageGPR);
     7202    m_jit.storeValue(valueRegs, JITCompiler::Address(storageGPR, node->capturedArgumentsOffset().offset() * sizeof(WriteBarrier<Unknown>)));
    71447203    noResult(node);
    71457204}
  • trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h

    r229053 r229518  
    5252    macro(CallFrame_callerFrame, CallFrame::callerFrameOffset()) \
    5353    macro(ClassInfo_parentClass, ClassInfo::offsetOfParentClass()) \
     54    macro(DirectArguments_Storage_length, DirectArguments::offsetOfLengthInStorage()) \
     55    macro(DirectArguments_Storage_minCapacity, DirectArguments::offsetOfMinCapacityInStorage()) \
    5456    macro(DirectArguments_callee, DirectArguments::offsetOfCallee()) \
    55     macro(DirectArguments_length, DirectArguments::offsetOfLength()) \
    56     macro(DirectArguments_minCapacity, DirectArguments::offsetOfMinCapacity()) \
    5757    macro(DirectArguments_mappedArguments, DirectArguments::offsetOfMappedArguments()) \
    5858    macro(DirectArguments_modifiedArgumentsDescriptor, DirectArguments::offsetOfModifiedArgumentsDescriptor()) \
     59    macro(DirectArguments_storage, DirectArguments::offsetOfStorage()) \
    5960    macro(GetterSetter_getter, GetterSetter::offsetOfGetter()) \
    6061    macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \
     
    134135    macro(ArrayStorage_vector, ArrayStorage::vectorOffset(), sizeof(WriteBarrier<Unknown>)) \
    135136    macro(CompleteSubspace_allocatorForSizeStep, CompleteSubspace::offsetOfAllocatorForSizeStep(), sizeof(Allocator)) \
    136     macro(DirectArguments_storage, DirectArguments::storageOffset(), sizeof(EncodedJSValue)) \
     137    macro(DirectArguments_Storage_storage, 0, sizeof(EncodedJSValue)) \
    137138    macro(JSLexicalEnvironment_variables, JSLexicalEnvironment::offsetOfVariables(), sizeof(EncodedJSValue)) \
    138139    macro(JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, 0, sizeof(WriteBarrier<JSString>)) \
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r229514 r229518  
    36743674                ExoticObjectMode, noValue(), nullptr,
    36753675                m_out.notNull(m_out.loadPtr(arguments, m_heaps.DirectArguments_mappedArguments)));
    3676             setInt32(m_out.load32NonNegative(arguments, m_heaps.DirectArguments_length));
     3676            LValue storage = m_out.bitXor(
     3677                m_out.loadPtr(lowCell(m_node->child1()), m_heaps.DirectArguments_storage),
     3678                m_out.constIntPtr(DirectArgumentsPoison::key()));
     3679            setInt32(m_out.load32NonNegative(storage, m_heaps.DirectArguments_Storage_length));
    36773680            return;
    36783681        }
     
    38403843                m_out.notNull(m_out.loadPtr(base, m_heaps.DirectArguments_mappedArguments)));
    38413844
    3842             LValue length = m_out.load32NonNegative(base, m_heaps.DirectArguments_length);
     3845            LValue storage = m_out.loadPtr(base, m_heaps.DirectArguments_storage);
     3846            storage = m_out.bitXor(storage, m_out.constIntPtr(DirectArgumentsPoison::key()));
     3847           
     3848            LValue length = m_out.load32NonNegative(storage, m_heaps.DirectArguments_Storage_length);
    38433849            auto isOutOfBounds = m_out.aboveOrEqual(index, length);
    38443850            if (m_node->arrayMode().isInBounds()) {
    38453851                speculate(OutOfBounds, noValue(), nullptr, isOutOfBounds);
    38463852                TypedPointer address = m_out.baseIndex(
    3847                     m_heaps.DirectArguments_storage, base, m_out.zeroExtPtr(index));
    3848                 setJSValue(m_out.load64(address));
     3853                    m_heaps.DirectArguments_Storage_storage, storage, m_out.zeroExtPtr(index));
     3854                setJSValue(preciseIndexMask32(m_out.load64(address), index, length));
    38493855                return;
    38503856            }
     
    38583864            LBasicBlock lastNext = m_out.appendTo(inBounds, slowCase);
    38593865            TypedPointer address = m_out.baseIndex(
    3860                 m_heaps.DirectArguments_storage,
    3861                 dynamicPoisonOnType(base, DirectArgumentsType),
     3866                m_heaps.DirectArguments_Storage_storage, storage,
    38623867                m_out.zeroExt(index, pointerType()));
    38633868            ValueFromBlock fastResult = m_out.anchor(
     
    51585163        ArgumentsLength length = getArgumentsLength();
    51595164       
     5165        LValue fastStorage;
    51605166        LValue fastObject;
    51615167        if (length.isKnown) {
    5162             fastObject = allocateObject<DirectArguments>(
    5163                 DirectArguments::allocationSize(std::max(length.known, minCapacity)), structure,
    5164                 m_out.intPtrZero, m_out.int32Zero, slowPath);
     5168            LValue allocator = m_out.constInt32(
     5169                vm().jsValueGigacageAuxiliarySpace.allocatorForNonVirtual(
     5170                    DirectArguments::storageSize(std::max(length.known, minCapacity)),
     5171                    AllocatorForMode::AllocatorIfExists).offset());
     5172
     5173            fastStorage = allocateHeapCell(allocator, slowPath);
    51655174        } else {
    51665175            LValue size = m_out.add(
    51675176                m_out.shl(length.value, m_out.constInt32(3)),
    5168                 m_out.constInt32(DirectArguments::storageOffset()));
     5177                m_out.constInt32(DirectArguments::storageHeaderSize()));
    51695178           
    51705179            size = m_out.select(
    51715180                m_out.aboveOrEqual(length.value, m_out.constInt32(minCapacity)),
    5172                 size, m_out.constInt32(DirectArguments::allocationSize(minCapacity)));
    5173            
    5174             fastObject = allocateVariableSizedObject<DirectArguments>(
    5175                 m_out.zeroExtPtr(size), structure, m_out.intPtrZero, m_out.int32Zero, slowPath);
    5176         }
    5177        
    5178         m_out.store32(length.value, fastObject, m_heaps.DirectArguments_length);
    5179         m_out.store32(m_out.constInt32(minCapacity), fastObject, m_heaps.DirectArguments_minCapacity);
     5181                size, m_out.constInt32(DirectArguments::storageSize(minCapacity)));
     5182       
     5183            fastStorage = allocateVariableSizedHeapCell(
     5184                vm().jsValueGigacageAuxiliarySpace, m_out.zeroExtPtr(size), slowPath);
     5185        }
     5186       
     5187        fastStorage = m_out.add(fastStorage, m_out.constIntPtr(DirectArguments::storageHeaderSize()));
     5188        m_out.store32(length.value, fastStorage, m_heaps.DirectArguments_Storage_length);
     5189        m_out.store32(m_out.constInt32(minCapacity), fastStorage, m_heaps.DirectArguments_Storage_minCapacity);
     5190       
     5191        fastObject = allocateObject<DirectArguments>(structure, m_out.intPtrZero, m_out.intPtrZero, slowPath);
     5192 
     5193        m_out.storePtr(m_out.bitXor(fastStorage, m_out.constIntPtr(DirectArgumentsPoison::key())), fastObject, m_heaps.DirectArguments_storage);
    51805194        m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_mappedArguments);
    51815195        m_out.storePtr(m_out.intPtrZero, fastObject, m_heaps.DirectArguments_modifiedArgumentsDescriptor);
    51825196       
     5197        ValueFromBlock fastStorageAnchor = m_out.anchor(fastStorage);
    51835198        ValueFromBlock fastResult = m_out.anchor(fastObject);
    51845199        m_out.jump(continuation);
     
    51945209            }, length.value);
    51955210        ValueFromBlock slowResult = m_out.anchor(callResult);
     5211        ValueFromBlock slowStorage = m_out.anchor(
     5212            m_out.bitXor(
     5213                m_out.loadPtr(callResult, m_heaps.DirectArguments_storage),
     5214                m_out.constIntPtr(DirectArgumentsPoison::key())));
    51965215        m_out.jump(continuation);
    51975216       
    51985217        m_out.appendTo(continuation, lastNext);
     5218        LValue storage = m_out.phi(pointerType(), fastStorageAnchor, slowStorage);
    51995219        LValue result = m_out.phi(pointerType(), fastResult, slowResult);
    52005220
     
    52065226                m_out.store64(
    52075227                    m_out.load64(addressFor(start + i)),
    5208                     result, m_heaps.DirectArguments_storage[i]);
     5228                    storage, m_heaps.DirectArguments_Storage_storage[i]);
    52095229            }
    52105230        } else {
     
    52345254            m_out.store64(
    52355255                m_out.load64(m_out.baseIndex(m_heaps.variables, stackBase, index)),
    5236                 m_out.baseIndex(m_heaps.DirectArguments_storage, result, index));
     5256                m_out.baseIndex(m_heaps.DirectArguments_Storage_storage, storage, index));
    52375257            ValueFromBlock nextIndex = m_out.anchor(index);
    52385258            m_out.addIncomingToPhi(previousIndex, nextIndex);
     
    66916711    void compileGetFromArguments()
    66926712    {
     6713        LValue storage = m_out.bitXor(
     6714            m_out.loadPtr(lowCell(m_node->child1()), m_heaps.DirectArguments_storage),
     6715            m_out.constIntPtr(DirectArgumentsPoison::key()));
    66936716        setJSValue(
    66946717            m_out.load64(
    6695                 lowCell(m_node->child1()),
    6696                 m_heaps.DirectArguments_storage[m_node->capturedArgumentsOffset().offset()]));
     6718                storage,
     6719                m_heaps.DirectArguments_Storage_storage[m_node->capturedArgumentsOffset().offset()]));
    66976720    }
    66986721   
    66996722    void compilePutToArguments()
    67006723    {
     6724        LValue storage = m_out.bitXor(
     6725            m_out.loadPtr(lowCell(m_node->child1()), m_heaps.DirectArguments_storage),
     6726            m_out.constIntPtr(DirectArgumentsPoison::key()));
    67016727        m_out.store64(
    6702             lowJSValue(m_node->child2()),
    6703             lowCell(m_node->child1()),
    6704             m_heaps.DirectArguments_storage[m_node->capturedArgumentsOffset().offset()]);
     6728            lowJSValue(m_node->child2()), storage,
     6729            m_heaps.DirectArguments_Storage_storage[m_node->capturedArgumentsOffset().offset()]);
    67056730    }
    67066731
     
    1184211867            LValue structure = loadStructure(cell);
    1184311868            LValue poisonedClassInfo = m_out.loadPtr(structure, m_heaps.Structure_classInfo);
    11844             LValue classInfo = m_out.bitXor(poisonedClassInfo, m_out.constInt64(GlobalDataPoison::key()));
     11869            LValue classInfo = m_out.bitXor(poisonedClassInfo, m_out.constIntPtr(GlobalDataPoison::key()));
    1184511870            ValueFromBlock otherAtStart = m_out.anchor(classInfo);
    1184611871            m_out.jump(loop);
     
    1261512640        LValue allocator = allocatorForSize(*subspaceFor<ClassType>(vm()), size, slowPath);
    1261612641        return allocateCell(allocator, structure, slowPath);
     12642    }
     12643   
     12644    LValue allocateVariableSizedHeapCell(CompleteSubspace& subspace, LValue size, LBasicBlock slowPath)
     12645    {
     12646        LValue allocator = allocatorForSize(subspace, size, slowPath);
     12647        return allocateHeapCell(allocator, slowPath);
    1261712648    }
    1261812649   
     
    1557315604    }
    1557415605   
    15575     LValue dynamicPoison(LValue value, LValue poison)
    15576     {
    15577         return m_out.add(
    15578             value,
    15579             m_out.shl(
    15580                 m_out.zeroExt(poison, pointerType()),
    15581                 m_out.constInt32(40)));
    15582     }
    15583    
    15584     LValue dynamicPoisonOnLoadedType(LValue value, LValue actualType, JSType expectedType)
    15585     {
    15586         return dynamicPoison(
    15587             value,
    15588             m_out.bitXor(
    15589                 m_out.opaque(actualType),
    15590                 m_out.constInt32(expectedType)));
    15591     }
    15592    
    15593     LValue dynamicPoisonOnType(LValue value, JSType expectedType)
    15594     {
    15595         return dynamicPoisonOnLoadedType(
    15596             value,
    15597             m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoType),
    15598             expectedType);
    15599     }
    15600 
    1560115606    template<typename... Args>
    1560215607    LValue vmCall(LType type, LValue function, Args&&... args)
  • trunk/Source/JavaScriptCore/heap/SecurityKind.h

    r228552 r229518  
    2828namespace JSC {
    2929
     30// NOTE: SecurityKind is for distancing. But caging implies distancing. So, things that have their own
     31// cages (like typed arrays) don't need to worry about the security kind.
    3032enum class SecurityKind : uint8_t {
    3133    // The JSValueOOB security kind is for cells that contain JValues and can be accessed out-of-bounds
     
    4244    // out-of-bounds. Currently, it's not essential to keep this separate from DangerousBits. We're
    4345    // using this to get some wiggle room for how we handle array elements. For example, we might want
    44     // to allow OOB reads but not OOB writes.
     46    // to allow OOB reads but not OOB writes, since JSValueStrict contains only JSValues and length fields.
     47    // Using Spectre to read the length fields is not useful for attackers since they can read them anyway.
     48    // So, they will only want to write to length fields, in order to confuse a subsequent bounds check.
     49    // They can do that within a speculation window. However, we currently use precise index masking for
     50    // this.
    4551    //
    4652    // It's illegal to use this for any subclass of JSObject, JSString, or Symbol, or any other cell
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r229391 r229518  
    11011101   
    11021102    emitGetVirtualRegister(arguments, regT0);
    1103     load64(Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>)), regT0);
     1103    loadPtr(Address(regT0, DirectArguments::offsetOfStorage()), regT0);
     1104    xorPtr(TrustedImmPtr(DirectArgumentsPoison::key()), regT0);
     1105    load64(Address(regT0, index * sizeof(WriteBarrier<Unknown>)), regT0);
    11041106    emitValueProfilingSite();
    11051107    emitPutVirtualRegister(dst);
     
    11141116    emitGetVirtualRegister(arguments, regT0);
    11151117    emitGetVirtualRegister(value, regT1);
    1116     store64(regT1, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>)));
     1118    loadPtr(Address(regT0, DirectArguments::offsetOfStorage()), regT0);
     1119    xorPtr(TrustedImmPtr(DirectArgumentsPoison::key()), regT0);
     1120    store64(regT1, Address(regT0, index * sizeof(WriteBarrier<Unknown>)));
    11171121
    11181122    emitWriteBarrier(arguments, value, ShouldFilterValue);
     
    14131417    load8(Address(base, JSCell::typeInfoTypeOffset()), scratch);
    14141418    badType = patchableBranch32(NotEqual, scratch, TrustedImm32(DirectArgumentsType));
    1415     emitDynamicPoisonOnLoadedType(base, scratch, DirectArgumentsType);
    1416    
    1417     load32(Address(base, DirectArguments::offsetOfLength()), scratch2);
     1419   
     1420    loadPtr(Address(base, DirectArguments::offsetOfStorage()), scratch);
     1421    xorPtr(TrustedImmPtr(DirectArgumentsPoison::key()), scratch);
     1422   
     1423    load32(Address(scratch, DirectArguments::offsetOfLengthInStorage()), scratch2);
    14181424    slowCases.append(branch32(AboveOrEqual, property, scratch2));
    14191425    slowCases.append(branchTestPtr(NonZero, Address(base, DirectArguments::offsetOfMappedArguments())));
    14201426   
    14211427    emitPreparePreciseIndexMask32(property, scratch2, scratch2);
    1422     loadValue(BaseIndex(base, property, TimesEight, DirectArguments::storageOffset()), result);
     1428    loadValue(BaseIndex(scratch, property, TimesEight), result);
    14231429    andPtr(scratch2, result.payloadGPR());
    14241430   
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r229391 r229518  
    11191119   
    11201120    emitLoadPayload(arguments, regT0);
    1121     load32(Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + TagOffset), regT1);
    1122     load32(Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + PayloadOffset), regT0);
     1121    loadPtr(Address(regT0, DirectArguments::offsetOfStorage()), regT0);
     1122    load32(Address(regT0, index * sizeof(WriteBarrier<Unknown>) + TagOffset), regT1);
     1123    load32(Address(regT0, index * sizeof(WriteBarrier<Unknown>) + PayloadOffset), regT0);
    11231124    emitValueProfilingSite();
    11241125    emitStore(dst, regT1, regT0);
     
    11341135   
    11351136    emitLoadPayload(arguments, regT0);
     1137    loadPtr(Address(regT0, DirectArguments::offsetOfStorage()), regT0);
    11361138    emitLoad(value, regT1, regT2);
    1137     store32(regT1, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + TagOffset));
    1138     store32(regT2, Address(regT0, DirectArguments::storageOffset() + index * sizeof(WriteBarrier<Unknown>) + PayloadOffset));
     1139    store32(regT1, Address(regT0, index * sizeof(WriteBarrier<Unknown>) + TagOffset));
     1140    store32(regT2, Address(regT0, index * sizeof(WriteBarrier<Unknown>) + PayloadOffset));
    11391141}
    11401142
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r229482 r229518  
    165165
    166166const JSLexicalEnvironment_variables = (sizeof JSLexicalEnvironment + SlotSize - 1) & ~(SlotSize - 1)
    167 const DirectArguments_storage = (sizeof DirectArguments + SlotSize - 1) & ~(SlotSize - 1)
    168167
    169168const StackAlignment = 16
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r229481 r229518  
    24972497    loadi PayloadOffset[cfr, t0, 8], t0
    24982498    loadi 12[PC], t1
    2499     loadi DirectArguments_storage + TagOffset[t0, t1, 8], t2
    2500     loadi DirectArguments_storage + PayloadOffset[t0, t1, 8], t3
     2499    loadp DirectArguments::m_storage[t0], t0
     2500    loadi TagOffset[t0, t1, 8], t2
     2501    loadi PayloadOffset[t0, t1, 8], t3
    25012502    loadisFromInstruction(1, t1)
    25022503    valueProfile(t2, t3, 16, t0)
     
    25132514    loadisFromInstruction(3, t1)
    25142515    loadConstantOrVariable(t1, t2, t3)
     2516    loadp DirectArguments::m_storage[t0], t0
    25152517    loadi 8[PC], t1
    2516     storei t2, DirectArguments_storage + TagOffset[t0, t1, 8]
    2517     storei t3, DirectArguments_storage + PayloadOffset[t0, t1, 8]
     2518    storei t2, TagOffset[t0, t1, 8]
     2519    storei t3, PayloadOffset[t0, t1, 8]
    25182520    dispatch(4)
    25192521
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r229482 r229518  
    25302530    loadVariable(2, t0)
    25312531    loadi 24[PB, PC, 8], t1
    2532     loadq DirectArguments_storage[t0, t1, 8], t0
     2532    loadp DirectArguments::m_storage[t0], t0
     2533    unpoison(_g_DirectArgumentsPoison, t0, t3)
     2534    loadq [t0, t1, 8], t0
    25332535    valueProfile(t0, 4, t1)
    25342536    loadisFromInstruction(1, t1)
     
    25432545    loadisFromInstruction(3, t3)
    25442546    loadConstantOrVariable(t3, t2)
    2545     storeq t2, DirectArguments_storage[t0, t1, 8]
     2547    loadp DirectArguments::m_storage[t0], t0
     2548    unpoison(_g_DirectArgumentsPoison, t0, t3)
     2549    storeq t2, [t0, t1, 8]
    25462550    writeBarrierOnOperands(1, 3)
    25472551    dispatch(constexpr op_put_to_arguments_length)
  • trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp

    r227617 r229518  
    3737const ClassInfo DirectArguments::s_info = { "Arguments", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DirectArguments) };
    3838
    39 DirectArguments::DirectArguments(VM& vm, Structure* structure, unsigned length, unsigned capacity)
     39DirectArguments::DirectArguments(VM& vm, Structure* structure, WriteBarrier<Unknown>* storage)
    4040    : GenericArguments(vm, structure)
    41     , m_length(length)
    42     , m_minCapacity(capacity)
     41    , m_storage(vm, this, storage)
    4342{
    4443    // When we construct the object from C++ code, we expect the capacity to be at least as large as
    4544    // length. JIT-allocated DirectArguments objects play evil tricks, though.
    46     ASSERT(capacity >= length);
     45    ASSERT(storageHeader(storage).minCapacity >= storageHeader(storage).length);
    4746}
    4847
     
    5049    VM& vm, Structure* structure, unsigned length, unsigned capacity)
    5150{
     51    void* rawStoragePtr = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(
     52        vm, storageSize(capacity), nullptr, AllocationFailureMode::Assert);
     53    WriteBarrier<Unknown>* storage = static_cast<WriteBarrier<Unknown>*>(rawStoragePtr) + 1;
     54    storageHeader(storage).length = length;
     55    storageHeader(storage).minCapacity = capacity;
     56   
    5257    DirectArguments* result =
    53         new (NotNull, allocateCell<DirectArguments>(vm.heap, allocationSize(capacity)))
    54         DirectArguments(vm, structure, length, capacity);
     58        new (NotNull, allocateCell<DirectArguments>(vm.heap))
     59        DirectArguments(vm, structure, storage);
    5560    result->finishCreation(vm);
    5661    return result;
     
    6065{
    6166    DirectArguments* result = createUninitialized(vm, structure, length, capacity);
    62    
     67
     68    WriteBarrier<Unknown>* storage = result->storage();
    6369    for (unsigned i = capacity; i--;)
    64         result->storage()[i].clear();
     70        storage[i].clear();
    6571   
    6672    return result;
     
    7682        vm, exec->lexicalGlobalObject()->directArgumentsStructure(), length, capacity);
    7783   
     84    WriteBarrier<Unknown>* storage = result->storage();
    7885    for (unsigned i = capacity; i--;)
    79         result->storage()[i].set(vm, result, exec->getArgumentUnsafe(i));
     86        storage[i].set(vm, result, exec->getArgumentUnsafe(i));
    8087   
    8188    result->callee().set(vm, result, jsCast<JSFunction*>(exec->jsCallee()));
     
    8895    DirectArguments* thisObject = jsCast<DirectArguments*>(cell);
    8996    size_t mappedArgumentsSize = thisObject->m_mappedArguments ? thisObject->mappedArgumentsSize() * sizeof(bool) : 0;
    90     size_t modifiedArgumentsSize = thisObject->m_modifiedArgumentsDescriptor ? thisObject->m_length * sizeof(bool) : 0;
     97    size_t modifiedArgumentsSize = thisObject->m_modifiedArgumentsDescriptor ? thisObject->storageHeader().length * sizeof(bool) : 0;
    9198    return Base::estimatedSize(cell) + mappedArgumentsSize + modifiedArgumentsSize;
    9299}
     
    98105    Base::visitChildren(thisObject, visitor);
    99106
    100     visitor.appendValues(thisObject->storage(), std::max(thisObject->m_length, thisObject->m_minCapacity));
     107    visitor.markAuxiliary(&thisObject->storageHeader());
     108    visitor.appendValues(thisObject->storage(), std::max(thisObject->storageHeader().length, thisObject->storageHeader().minCapacity));
     109   
    101110    visitor.append(thisObject->m_callee);
    102111
    103112    if (thisObject->m_mappedArguments)
    104113        visitor.markAuxiliary(thisObject->m_mappedArguments.get());
     114   
    105115    GenericArguments<DirectArguments>::visitChildren(thisCell, visitor);
    106116}
     
    115125    RELEASE_ASSERT(!m_mappedArguments);
    116126   
    117     putDirect(vm, vm.propertyNames->length, jsNumber(m_length), static_cast<unsigned>(PropertyAttribute::DontEnum));
     127    putDirect(vm, vm.propertyNames->length, jsNumber(storageHeader().length), static_cast<unsigned>(PropertyAttribute::DontEnum));
    118128    putDirect(vm, vm.propertyNames->callee, m_callee.get(), static_cast<unsigned>(PropertyAttribute::DontEnum));
    119129    putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayProtoValuesFunction(), static_cast<unsigned>(PropertyAttribute::DontEnum));
     
    122132    bool* overrides = static_cast<bool*>(backingStore);
    123133    m_mappedArguments.set(vm, this, overrides);
    124     for (unsigned i = m_length; i--;)
     134    for (unsigned i = storageHeader().length; i--;)
    125135        overrides[i] = false;
    126136}
     
    141151{
    142152    if (!m_mappedArguments) {
    143         unsigned limit = std::min(length + offset, m_length);
     153        unsigned limit = std::min(length + offset, storageHeader().length);
    144154        unsigned i;
    145155        VirtualRegister start = firstElementDest - offset;
     156        WriteBarrier<Unknown>* storage = this->storage();
    146157        for (i = offset; i < limit; ++i)
    147             exec->r(start + i) = storage()[i].get();
     158            exec->r(start + i) = storage[i].get();
    148159        for (; i < length; ++i)
    149160            exec->r(start + i) = get(exec, i);
     
    159170    // still allocate so that m_mappedArguments is non-null. We use that to indicate that the other properties
    160171    // (length, etc) are overridden.
    161     return WTF::roundUpToMultipleOf<8>(m_length ? m_length : 1);
     172    return WTF::roundUpToMultipleOf<8>(storageHeader().length ? storageHeader().length : 1);
    162173}
    163174
  • trunk/Source/JavaScriptCore/runtime/DirectArguments.h

    r229362 r229518  
    3333namespace JSC {
    3434
     35class LLIntOffsetsExtractor;
     36   
    3537// This is an Arguments-class object that we create when you say "arguments" inside a function,
    3638// and none of the arguments are captured in the function's activation. The function will copy all
     
    3941// being deleted (something like "delete arguments[0]") or reconfigured (broadly, we say deletions
    4042// and reconfigurations mean that the respective argument was "overridden").
    41 //
    42 // To speed allocation, this object will hold all of the arguments in-place. The arguments as well
    43 // as a table of flags saying which arguments were overridden.
    4443class DirectArguments final : public GenericArguments<DirectArguments> {
    4544private:
    46     DirectArguments(VM&, Structure*, unsigned length, unsigned capacity);
     45    DirectArguments(VM&, Structure*, WriteBarrier<Unknown>* storage);
    4746   
    4847public:
    4948    template<typename CellType>
    50     static CompleteSubspace* subspaceFor(VM& vm)
     49    static IsoSubspace* subspaceFor(VM& vm)
    5150    {
    5251        RELEASE_ASSERT(!CellType::needsDestruction);
    53         return &vm.jsValueGigacageCellSpace;
     52        return &vm.directArgumentsSpace;
    5453    }
    5554
     
    7069    uint32_t internalLength() const
    7170    {
    72         return m_length;
     71        return storageHeader().length;
    7372    }
    7473   
     
    8382            return value.toUInt32(exec);
    8483        }
    85         return m_length;
     84        return storageHeader().length;
    8685    }
    8786   
    8887    bool isMappedArgument(uint32_t i) const
    8988    {
    90         return i < m_length && (!m_mappedArguments || !m_mappedArguments[i]);
     89        return i < storageHeader().length && (!m_mappedArguments || !m_mappedArguments[i]);
    9190    }
    9291
    9392    bool isMappedArgumentInDFG(uint32_t i) const
    9493    {
    95         return i < m_length && !overrodeThings();
    96     }
    97 
     94        return i < storageHeader().length && !overrodeThings();
     95    }
     96   
    9897    JSValue getIndexQuickly(uint32_t i) const
    9998    {
    10099        ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
    101         auto* ptr = &const_cast<DirectArguments*>(this)->storage()[i];
    102         return preciseIndexMaskPtr(i, m_length, dynamicPoison(type(), DirectArgumentsType, ptr))->get();
     100        WriteBarrier<Unknown>* storage = this->storage();
     101        auto* ptr = &storage[i];
     102        return preciseIndexMaskPtr(i, storageHeader(storage).length, ptr)->get();
    103103    }
    104104   
     
    106106    {
    107107        ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
    108         auto* ptr = &storage()[i];
    109         preciseIndexMaskPtr(i, m_length, dynamicPoison(type(), DirectArgumentsType, ptr))->set(vm, this, value);
     108        WriteBarrier<Unknown>* storage = this->storage();
     109        auto* ptr = &storage[i];
     110        preciseIndexMaskPtr(i, storageHeader(storage).length, ptr)->set(vm, this, value);
    110111    }
    111112   
     
    118119    {
    119120        ASSERT(offset);
    120         ASSERT_WITH_SECURITY_IMPLICATION(offset.offset() < std::max(m_length, m_minCapacity));
    121         auto* ptr = &storage()[offset.offset()];
    122         return *preciseIndexMaskPtr(offset.offset(), std::max(m_length, m_minCapacity), dynamicPoison(type(), DirectArgumentsType, ptr));
     121        ASSERT_WITH_SECURITY_IMPLICATION(offset.offset() < std::max(storageHeader().length, storageHeader().minCapacity));
     122        WriteBarrier<Unknown>* storage = this->storage();
     123        auto* ptr = &storage[offset.offset()];
     124        return *preciseIndexMaskPtr(
     125            offset.offset(),
     126            std::max(storageHeader(storage).length, storageHeader(storage).minCapacity),
     127            ptr);
    123128    }
    124129   
     
    131136    void initModifiedArgumentsDescriptorIfNecessary(VM& vm)
    132137    {
    133         GenericArguments<DirectArguments>::initModifiedArgumentsDescriptorIfNecessary(vm, m_length);
     138        GenericArguments<DirectArguments>::initModifiedArgumentsDescriptorIfNecessary(vm, storageHeader().length);
    134139    }
    135140
    136141    void setModifiedArgumentDescriptor(VM& vm, unsigned index)
    137142    {
    138         GenericArguments<DirectArguments>::setModifiedArgumentDescriptor(vm, index, m_length);
     143        GenericArguments<DirectArguments>::setModifiedArgumentDescriptor(vm, index, storageHeader().length);
    139144    }
    140145
    141146    bool isModifiedArgumentDescriptor(unsigned index)
    142147    {
    143         return GenericArguments<DirectArguments>::isModifiedArgumentDescriptor(index, m_length);
     148        return GenericArguments<DirectArguments>::isModifiedArgumentDescriptor(index, storageHeader().length);
    144149    }
    145150
     
    151156   
    152157    static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(DirectArguments, m_callee); }
    153     static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(DirectArguments, m_length); }
    154     static ptrdiff_t offsetOfMinCapacity() { return OBJECT_OFFSETOF(DirectArguments, m_minCapacity); }
    155158    static ptrdiff_t offsetOfMappedArguments() { return OBJECT_OFFSETOF(DirectArguments, m_mappedArguments); }
    156159    static ptrdiff_t offsetOfModifiedArgumentsDescriptor() { return OBJECT_OFFSETOF(DirectArguments, m_modifiedArgumentsDescriptor); }
    157    
    158     static size_t storageOffset()
    159     {
    160         return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(DirectArguments));
    161     }
    162    
    163     static size_t offsetOfSlot(Checked<size_t> index)
    164     {
    165         return (storageOffset() + sizeof(WriteBarrier<Unknown>) * index).unsafeGet();
    166     }
    167    
    168     static size_t allocationSize(Checked<size_t> capacity)
    169     {
    170         return offsetOfSlot(capacity);
     160    static ptrdiff_t offsetOfStorage() { return OBJECT_OFFSETOF(DirectArguments, m_storage); }
     161
     162    static ptrdiff_t offsetOfLengthInStorage() { return OBJECT_OFFSETOF(StorageHeader, length) - sizeof(WriteBarrier<Unknown>); }
     163    static ptrdiff_t offsetOfMinCapacityInStorage() { return OBJECT_OFFSETOF(StorageHeader, minCapacity) - sizeof(WriteBarrier<Unknown>); }
     164   
     165    static size_t storageSize(Checked<size_t> capacity)
     166    {
     167        return (sizeof(WriteBarrier<Unknown>) * (capacity + static_cast<size_t>(1))).unsafeGet();
     168    }
     169   
     170    static size_t storageHeaderSize() { return sizeof(WriteBarrier<Unknown>); }
     171   
     172    static size_t allocationSize(size_t inlineSize)
     173    {
     174        RELEASE_ASSERT(!inlineSize);
     175        return sizeof(DirectArguments);
    171176    }
    172177   
    173178private:
    174     WriteBarrier<Unknown>* storage()
    175     {
    176         return bitwise_cast<WriteBarrier<Unknown>*>(bitwise_cast<char*>(this) + storageOffset());
     179    friend class LLIntOffsetsExtractor;
     180   
     181    struct StorageHeader {
     182        uint32_t length; // Always the actual length of captured arguments and never what was stored into the length property.
     183        uint32_t minCapacity; // The max of this and length determines the capacity of this object. It may be the actual capacity, or maybe something smaller. We arrange it this way to be kind to the JITs.
     184    };
     185   
     186    WriteBarrier<Unknown>* storage() const
     187    {
     188        return m_storage.get().unpoisoned();
     189    }
     190   
     191    static StorageHeader& storageHeader(WriteBarrier<Unknown>* storage)
     192    {
     193        static_assert(sizeof(StorageHeader) == sizeof(WriteBarrier<Unknown>), "StorageHeader needs to be the same size as a JSValue");
     194        return *bitwise_cast<StorageHeader*>(storage - 1);
     195    }
     196
     197    StorageHeader& storageHeader() const
     198    {
     199        return storageHeader(storage());
    177200    }
    178201   
     
    180203   
    181204    WriteBarrier<JSFunction> m_callee;
    182     uint32_t m_length; // Always the actual length of captured arguments and never what was stored into the length property.
    183     uint32_t m_minCapacity; // The max of this and length determines the capacity of this object. It may be the actual capacity, or maybe something smaller. We arrange it this way to be kind to the JITs.
    184205    CagedBarrierPtr<Gigacage::Primitive, bool> m_mappedArguments; // If non-null, it means that length, callee, and caller are fully materialized properties.
     206    AuxiliaryBarrier<Poisoned<DirectArgumentsPoison, WriteBarrier<Unknown>*>> m_storage;
    185207};
    186208
  • trunk/Source/JavaScriptCore/runtime/JSCPoison.h

    r228420 r229518  
    3535    v(CodeBlock) \
    3636    v(DateInstance) \
     37    v(DirectArguments) \
    3738    v(GlobalData) \
    3839    v(JITCode) \
  • trunk/Source/JavaScriptCore/runtime/JSLexicalEnvironment.h

    r229410 r229518  
    3737class LLIntOffsetsExtractor;
    3838
     39// This is Spectre-safe because it doesn't have its length inline.
    3940class JSLexicalEnvironment : public JSSymbolTableObject {
    4041    friend class JIT;
  • trunk/Source/JavaScriptCore/runtime/JSSymbolTableObject.h

    r222473 r229518  
    7474   
    7575private:
     76    // FIXME: This needs to be poisoned.
    7677    WriteBarrier<SymbolTable> m_symbolTable;
    7778};
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r229309 r229518  
    262262    , boundFunctionSpace ISO_SUBSPACE_INIT(heap, cellJSValueOOBHeapCellType.get(), JSBoundFunction)
    263263    , customGetterSetterFunctionSpace ISO_SUBSPACE_INIT(heap, cellJSValueOOBHeapCellType.get(), JSCustomGetterSetterFunction)
     264    , directArgumentsSpace ISO_SUBSPACE_INIT(heap, cellJSValueOOBHeapCellType.get(), DirectArguments)
    264265    , directEvalExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), DirectEvalExecutable)
    265266    , executableToCodeBlockEdgeSpace ISO_SUBSPACE_INIT(heap, cellDangerousBitsHeapCellType.get(), ExecutableToCodeBlockEdge)
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r229309 r229518  
    346346    IsoSubspace boundFunctionSpace;
    347347    IsoSubspace customGetterSetterFunctionSpace;
     348    IsoSubspace directArgumentsSpace;
    348349    IsoSubspace directEvalExecutableSpace;
    349350    IsoSubspace executableToCodeBlockEdgeSpace;
  • trunk/Source/WTF/ChangeLog

    r229515 r229518  
     12018-03-11  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Split DirectArguments into JSValueOOB and JSValueStrict parts
     4        https://bugs.webkit.org/show_bug.cgi?id=183458
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        * wtf/MathExtras.h:
     9        (WTF::dynamicPoison): Deleted.
     10
    1112018-03-11  Yusuke Suzuki  <utatane.tea@gmail.com>
    212
  • trunk/Source/WTF/wtf/MathExtras.h

    r229412 r229518  
    501501}
    502502
     503// This masks the given pointer with 0xffffffffffffffff (ptrwidth) if `index <
     504// length`. Otherwise, it masks the pointer with 0. Similar to Linux kernel's array_ptr.
    503505template<typename T>
    504506inline T* preciseIndexMaskPtr(uintptr_t index, uintptr_t length, T* value)
     
    510512}
    511513
    512 constexpr unsigned bytePoisonShift = 40;
    513 
    514 template<typename T, typename U>
    515 inline T* dynamicPoison(U actual, U expected, T* pointer)
    516 {
    517     static_assert(sizeof(U) == 1, "Poisoning only works for bytes at the moment");
    518 #if CPU(X86_64) || (CPU(ARM64) && !defined(__ILP32__))
    519     return bitwise_cast<T*>(
    520         bitwise_cast<char*>(pointer) +
    521         (static_cast<uintptr_t>(opaque(actual) ^ expected) << bytePoisonShift));
    522 #else
    523     UNUSED_PARAM(actual);
    524     UNUSED_PARAM(expected);
    525     return pointer;
    526 #endif
    527 }
    528 
    529514template<typename VectorType, typename RandomFunc>
    530515void shuffleVector(VectorType& vector, size_t size, const RandomFunc& randomFunc)
     
    542527} // namespace WTF
    543528
    544 using WTF::dynamicPoison;
    545529using WTF::opaque;
    546530using WTF::preciseIndexMaskPtr;
Note: See TracChangeset for help on using the changeset viewer.