Changeset 207266 in webkit


Ignore:
Timestamp:
Oct 12, 2016 6:42:53 PM (7 years ago)
Author:
keith_miller@apple.com
Message:

B3 needs a special WasmBoundsCheck Opcode
https://bugs.webkit.org/show_bug.cgi?id=163246

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

This patch adds a new Opcode, WasmBoundsCheck, as well as a B3::Value subclass for it,
WasmBoundsCheckValue. WasmBoundsCheckValue takes three pieces of information. The first is
the Int32 pointer value used to be used by the Load. Next is the pinned register. The
pinned register must be pinned by calling proc.setPinned() prior to compiling the
Procedure. Lastly, the WasmBoundsCheckValue takes an offset. The WasmBoundsCheckValue is
will then emit code that side-exits if the Int64 sum of the offset and pointer is greater
than or equal to the value in the pinnedRegister. Instead of taking a generator for each
value like Check/Patchpoint, WasmBoundsCheck gets its generator directly off Air::Code. In
Air this patch adds a new Custom opcode, WasmBoundsCheck.

In the future we should add WasmBoundsCheck to CSE so it can eliminate redundant bounds
checks. At the first cut, we can remove any WasmBoundsCheck dominated by another
WasmBoundsCheck with the same pointer and pinnedGPR, and a larger offset.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • b3/B3LowerToAir.cpp:

(JSC::B3::Air::LowerToAir::imm):
(JSC::B3::Air::LowerToAir::lower):

  • b3/B3Opcode.cpp:

(WTF::printInternal):

  • b3/B3Opcode.h:
  • b3/B3Procedure.cpp:

(JSC::B3::Procedure::setWasmBoundsCheckGenerator):

  • b3/B3Procedure.h:

(JSC::B3::Procedure::setWasmBoundsCheckGenerator):

  • b3/B3Validate.cpp:
  • b3/B3Value.cpp:

(JSC::B3::Value::effects):
(JSC::B3::Value::typeFor):

  • b3/B3WasmBoundsCheckValue.cpp: Added.

(JSC::B3::WasmBoundsCheckValue::~WasmBoundsCheckValue):
(JSC::B3::WasmBoundsCheckValue::WasmBoundsCheckValue):
(JSC::B3::WasmBoundsCheckValue::dumpMeta):

  • b3/B3WasmBoundsCheckValue.h: Added.

(JSC::B3::WasmBoundsCheckValue::accepts):
(JSC::B3::WasmBoundsCheckValue::pinnedGPR):
(JSC::B3::WasmBoundsCheckValue::offset):

  • b3/air/AirCode.h:

(JSC::B3::Air::Code::setWasmBoundsCheckGenerator):
(JSC::B3::Air::Code::wasmBoundsCheckGenerator):

  • b3/air/AirCustom.cpp:

(JSC::B3::Air::WasmBoundsCheckCustom::isValidForm):

  • b3/air/AirCustom.h:

(JSC::B3::Air::WasmBoundsCheckCustom::forEachArg):
(JSC::B3::Air::WasmBoundsCheckCustom::isValidFormStatic):
(JSC::B3::Air::WasmBoundsCheckCustom::admitsStack):
(JSC::B3::Air::WasmBoundsCheckCustom::isTerminal):
(JSC::B3::Air::WasmBoundsCheckCustom::hasNonArgNonControlEffects):
(JSC::B3::Air::WasmBoundsCheckCustom::generate):

  • b3/air/AirOpcode.opcodes:
  • b3/testb3.cpp:

(JSC::B3::testWasmBoundsCheck):
(JSC::B3::run):

Websites/webkit.org:

Update the docs for the new WasmBoundsCheck opcode.

  • docs/b3/intermediate-representation.html:
Location:
trunk
Files:
2 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r207004 r207266  
    173173    b3/B3Variable.cpp
    174174    b3/B3VariableValue.cpp
     175    b3/B3WasmBoundsCheckValue.cpp
    175176
    176177    bindings/ScriptFunctionCall.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r207263 r207266  
     12016-10-12  Keith Miller  <keith_miller@apple.com>
     2
     3        B3 needs a special WasmBoundsCheck Opcode
     4        https://bugs.webkit.org/show_bug.cgi?id=163246
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch adds a new Opcode, WasmBoundsCheck, as well as a B3::Value subclass for it,
     9        WasmBoundsCheckValue. WasmBoundsCheckValue takes three pieces of information. The first is
     10        the Int32 pointer value used to be used by the Load.  Next is the pinned register. The
     11        pinned register must be pinned by calling proc.setPinned() prior to compiling the
     12        Procedure. Lastly, the WasmBoundsCheckValue takes an offset. The WasmBoundsCheckValue is
     13        will then emit code that side-exits if the Int64 sum of the offset and pointer is greater
     14        than or equal to the value in the pinnedRegister. Instead of taking a generator for each
     15        value like Check/Patchpoint, WasmBoundsCheck gets its generator directly off Air::Code. In
     16        Air this patch adds a new Custom opcode, WasmBoundsCheck.
     17
     18        In the future we should add WasmBoundsCheck to CSE so it can eliminate redundant bounds
     19        checks. At the first cut, we can remove any WasmBoundsCheck dominated by another
     20        WasmBoundsCheck with the same pointer and pinnedGPR, and a larger offset.
     21
     22        * CMakeLists.txt:
     23        * JavaScriptCore.xcodeproj/project.pbxproj:
     24        * b3/B3LowerToAir.cpp:
     25        (JSC::B3::Air::LowerToAir::imm):
     26        (JSC::B3::Air::LowerToAir::lower):
     27        * b3/B3Opcode.cpp:
     28        (WTF::printInternal):
     29        * b3/B3Opcode.h:
     30        * b3/B3Procedure.cpp:
     31        (JSC::B3::Procedure::setWasmBoundsCheckGenerator):
     32        * b3/B3Procedure.h:
     33        (JSC::B3::Procedure::setWasmBoundsCheckGenerator):
     34        * b3/B3Validate.cpp:
     35        * b3/B3Value.cpp:
     36        (JSC::B3::Value::effects):
     37        (JSC::B3::Value::typeFor):
     38        * b3/B3WasmBoundsCheckValue.cpp: Added.
     39        (JSC::B3::WasmBoundsCheckValue::~WasmBoundsCheckValue):
     40        (JSC::B3::WasmBoundsCheckValue::WasmBoundsCheckValue):
     41        (JSC::B3::WasmBoundsCheckValue::dumpMeta):
     42        * b3/B3WasmBoundsCheckValue.h: Added.
     43        (JSC::B3::WasmBoundsCheckValue::accepts):
     44        (JSC::B3::WasmBoundsCheckValue::pinnedGPR):
     45        (JSC::B3::WasmBoundsCheckValue::offset):
     46        * b3/air/AirCode.h:
     47        (JSC::B3::Air::Code::setWasmBoundsCheckGenerator):
     48        (JSC::B3::Air::Code::wasmBoundsCheckGenerator):
     49        * b3/air/AirCustom.cpp:
     50        (JSC::B3::Air::WasmBoundsCheckCustom::isValidForm):
     51        * b3/air/AirCustom.h:
     52        (JSC::B3::Air::WasmBoundsCheckCustom::forEachArg):
     53        (JSC::B3::Air::WasmBoundsCheckCustom::isValidFormStatic):
     54        (JSC::B3::Air::WasmBoundsCheckCustom::admitsStack):
     55        (JSC::B3::Air::WasmBoundsCheckCustom::isTerminal):
     56        (JSC::B3::Air::WasmBoundsCheckCustom::hasNonArgNonControlEffects):
     57        (JSC::B3::Air::WasmBoundsCheckCustom::generate):
     58        * b3/air/AirOpcode.opcodes:
     59        * b3/testb3.cpp:
     60        (JSC::B3::testWasmBoundsCheck):
     61        (JSC::B3::run):
     62
    1632016-10-12  Filip Pizlo  <fpizlo@apple.com>
    264
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r207239 r207266  
    12071207                531374BD1D5CE67600AF7A0B /* WASMPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 531374BC1D5CE67600AF7A0B /* WASMPlan.h */; };
    12081208                531374BF1D5CE95000AF7A0B /* WASMPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531374BE1D5CE95000AF7A0B /* WASMPlan.cpp */; };
     1209                5341FC701DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5341FC6F1DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp */; };
     1210                5341FC721DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 5341FC711DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h */; };
    12091211                53486BB71C1795C300F6F3AF /* JSTypedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 53486BB61C1795C300F6F3AF /* JSTypedArray.h */; settings = {ATTRIBUTES = (Public, ); }; };
    12101212                53486BBB1C18E84500F6F3AF /* JSTypedArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */; };
     
    34423444                531374BC1D5CE67600AF7A0B /* WASMPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMPlan.h; sourceTree = "<group>"; };
    34433445                531374BE1D5CE95000AF7A0B /* WASMPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WASMPlan.cpp; sourceTree = "<group>"; };
     3446                5341FC6F1DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3WasmBoundsCheckValue.cpp; path = b3/B3WasmBoundsCheckValue.cpp; sourceTree = "<group>"; };
     3447                5341FC711DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3WasmBoundsCheckValue.h; path = b3/B3WasmBoundsCheckValue.h; sourceTree = "<group>"; };
    34443448                53486BB61C1795C300F6F3AF /* JSTypedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypedArray.h; sourceTree = "<group>"; };
    34453449                53486BBA1C18E84500F6F3AF /* JSTypedArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArray.cpp; sourceTree = "<group>"; };
     
    48584862                                0FEC84BA1BDACDAC0080FF74 /* B3BlockWorklist.h */,
    48594863                                DCFDFBD71D1F5D9800FE3D72 /* B3BottomProvider.h */,
     4864                                5341FC6F1DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp */,
     4865                                5341FC711DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h */,
    48604866                                0F6B8ADE1C4EFE1700969052 /* B3BreakCriticalEdges.cpp */,
    48614867                                0F6B8ADF1C4EFE1700969052 /* B3BreakCriticalEdges.h */,
     
    76517657                                0F1E3A67153A21E2000F9456 /* DFGSilentRegisterSavePlan.h in Headers */,
    76527658                                0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */,
     7659                                5341FC721DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h in Headers */,
    76537660                                86EC9DD31328DF82002B2AD7 /* DFGSpeculativeJIT.h in Headers */,
    76547661                                0F682FB319BCB36400FA3BAD /* DFGSSACalculator.h in Headers */,
     
    93669373                                0F766D2F15A8DCE0008F363E /* GCAwareJITStubRoutine.cpp in Sources */,
    93679374                                2ADFA26318EF3540004F9FCC /* GCLogging.cpp in Sources */,
     9375                                5341FC701DAC33E500E7E4D7 /* B3WasmBoundsCheckValue.cpp in Sources */,
    93689376                                0F93329F14CA7DCA0085F3C6 /* GetByIdStatus.cpp in Sources */,
    93699377                                0F0332C318B01763005F979A /* GetByIdVariant.cpp in Sources */,
  • trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp

    r207163 r207266  
    569569    }
    570570
     571    Arg imm(int64_t intValue)
     572    {
     573        if (Arg::isValidImmForm(intValue))
     574            return Arg::imm(intValue);
     575        return Arg();
     576    }
     577
    571578    Arg imm(Value* value)
    572579    {
    573         if (value->hasInt()) {
    574             int64_t intValue = value->asInt();
    575             if (Arg::isValidImmForm(intValue))
    576                 return Arg::imm(intValue);
    577         }
     580        if (value->hasInt())
     581            return imm(value->asInt());
    578582        return Arg();
    579583    }
     
    26282632        }
    26292633
     2634        case B3::WasmBoundsCheck: {
     2635            WasmBoundsCheckValue* value = m_value->as<WasmBoundsCheckValue>();
     2636
     2637            Value* ptr = value->child(0);
     2638
     2639            Arg temp = m_code.newTmp(Arg::GP);
     2640            append(Inst(Move32, value, tmp(ptr), temp));
     2641            if (value->offset()) {
     2642                if (imm(value->offset()))
     2643                    append(Add64, imm(value->offset()), temp);
     2644                else {
     2645                    Arg bigImm = m_code.newTmp(Arg::GP);
     2646                    append(Move, Arg::bigImm(value->offset()), bigImm);
     2647                    append(Add64, bigImm, temp);
     2648                }
     2649            }
     2650            append(Inst(Air::WasmBoundsCheck, value, temp, Arg(value->pinnedGPR())));
     2651            return;
     2652        }
     2653
    26302654        case Upsilon: {
    26312655            Value* value = m_value->child(0);
  • trunk/Source/JavaScriptCore/b3/B3Opcode.cpp

    r206595 r207266  
    273273        out.print("Check");
    274274        return;
     275    case WasmBoundsCheck:
     276        out.print("WasmBoundsCheck");
     277        return;
    275278    case Upsilon:
    276279        out.print("Upsilon");
  • trunk/Source/JavaScriptCore/b3/B3Opcode.h

    r206595 r207266  
    210210    Check,
    211211
     212    // Special Wasm opcode that takes a Int32, a special pinned gpr and an offset. This node exists
     213    // to allow us to CSE WasmBoundsChecks if both use the same pointer and one dominates the other.
     214    // Without some such node B3 would not have enough information about the inner workings of wasm
     215    // to be able to perform such optimizations.
     216    WasmBoundsCheck,
     217
    212218    // SSA support, in the style of DFG SSA.
    213219    Upsilon, // This uses the UpsilonValue class.
  • trunk/Source/JavaScriptCore/b3/B3Procedure.cpp

    r207004 r207266  
    349349}
    350350
     351void Procedure::setWasmBoundsCheckGenerator(RefPtr<WasmBoundsCheckGenerator> generator)
     352{
     353    code().setWasmBoundsCheckGenerator(generator);
     354}
     355
    351356} } // namespace JSC::B3
    352357
  • trunk/Source/JavaScriptCore/b3/B3Procedure.h

    r207004 r207266  
    5959namespace Air { class Code; }
    6060
     61typedef void WasmBoundsCheckGeneratorFunction(CCallHelpers&, GPRReg, unsigned);
     62typedef SharedTask<WasmBoundsCheckGeneratorFunction> WasmBoundsCheckGenerator;
     63
    6164// This represents B3's view of a piece of code. Note that this object must exist in a 1:1
    6265// relationship with Air::Code. B3::Procedure and Air::Code are just different facades of the B3
     
    221224    PCToOriginMap& pcToOriginMap() { return m_pcToOriginMap; }
    222225    PCToOriginMap releasePCToOriginMap() { return WTFMove(m_pcToOriginMap); }
     226
     227    JS_EXPORT_PRIVATE void setWasmBoundsCheckGenerator(RefPtr<WasmBoundsCheckGenerator>);
     228
     229    template<typename Functor>
     230    void setWasmBoundsCheckGenerator(const Functor& functor)
     231    {
     232        setWasmBoundsCheckGenerator(RefPtr<WasmBoundsCheckGenerator>(createSharedTask<WasmBoundsCheckGeneratorFunction>(functor)));
     233    }
    223234
    224235private:
  • trunk/Source/JavaScriptCore/b3/B3Validate.cpp

    r206694 r207266  
    2929#if ENABLE(B3_JIT)
    3030
     31#include "AirCode.h"
    3132#include "B3ArgumentRegValue.h"
    3233#include "B3BasicBlockInlines.h"
     
    4142#include "B3Variable.h"
    4243#include "B3VariableValue.h"
     44#include "B3WasmBoundsCheckValue.h"
    4345#include <wtf/HashSet.h>
    4446#include <wtf/StringPrintStream.h>
     
    413415                VALIDATE(value->as<StackmapValue>()->constrainedChild(0).rep() == ValueRep::WarmAny, ("At ", *value));
    414416                validateStackmap(value);
     417                break;
     418            case WasmBoundsCheck:
     419                VALIDATE(!value->kind().hasExtraBits(), ("At ", *value));
     420                VALIDATE(value->numChildren() == 1, ("At ", *value));
     421                VALIDATE(value->child(0)->type() == Int32, ("At ", *value));
     422                VALIDATE(m_procedure.code().isPinned(value->as<WasmBoundsCheckValue>()->pinnedGPR()), ("At ", *value));
     423                VALIDATE(m_procedure.code().wasmBoundsCheckGenerator(), ("At ", *value));
    415424                break;
    416425            case Upsilon:
  • trunk/Source/JavaScriptCore/b3/B3Value.cpp

    r206846 r207266  
    616616    case Check:
    617617        result = Effects::forCheck();
     618        break;
     619    case WasmBoundsCheck:
     620        result.readsPinned = true;
     621        result.exitsSideways = true;
    618622        break;
    619623    case Upsilon:
     
    810814    case Oops:
    811815    case EntrySwitch:
     816    case WasmBoundsCheck:
    812817        return Void;
    813818    case Select:
  • trunk/Source/JavaScriptCore/b3/air/AirCode.h

    r207004 r207266  
    5353class CCallSpecial;
    5454
     55typedef void WasmBoundsCheckGeneratorFunction(CCallHelpers&, GPRReg, unsigned);
     56typedef SharedTask<WasmBoundsCheckGeneratorFunction> WasmBoundsCheckGenerator;
     57
    5558// This is an IR that is very close to the bare metal. It requires about 40x more bytes than the
    5659// generated machine code - for example if you're generating 1MB of machine code, you need about
     
    261264
    262265    const char* lastPhaseName() const { return m_lastPhaseName; }
     266
     267    void setWasmBoundsCheckGenerator(RefPtr<WasmBoundsCheckGenerator> generator)
     268    {
     269        m_wasmBoundsCheckGenerator = generator;
     270    }
     271
     272    RefPtr<WasmBoundsCheckGenerator> wasmBoundsCheckGenerator() const { return m_wasmBoundsCheckGenerator; }
    263273
    264274    // This is a hash of the code. You can use this if you want to put code into a hashtable, but
     
    299309    Vector<FrequentedBlock> m_entrypoints; // This is empty until after lowerEntrySwitch().
    300310    Vector<CCallHelpers::Label> m_entrypointLabels; // This is empty until code generation.
     311    RefPtr<WasmBoundsCheckGenerator> m_wasmBoundsCheckGenerator;
    301312    const char* m_lastPhaseName;
    302313};
  • trunk/Source/JavaScriptCore/b3/air/AirCustom.cpp

    r195298 r207266  
    179179}
    180180
     181bool WasmBoundsCheckCustom::isValidForm(Inst& inst)
     182{
     183    if (inst.args.size() != 2)
     184        return false;
     185    if (!inst.args[0].isTmp() && !inst.args[0].isSomeImm())
     186        return false;
     187
     188    return inst.args[1].isReg();
     189}
     190
     191
    181192} } } // namespace JSC::B3::Air
    182193
  • trunk/Source/JavaScriptCore/b3/air/AirCustom.h

    r206525 r207266  
    2828#if ENABLE(B3_JIT)
    2929
     30#include "AirCode.h"
     31#include "AirGenerationContext.h"
    3032#include "AirInst.h"
    3133#include "AirSpecial.h"
    32 #include "B3Value.h"
     34#include "B3ValueInlines.h"
     35#include "B3WasmBoundsCheckValue.h"
    3336
    3437namespace JSC { namespace B3 { namespace Air {
     
    274277};
    275278
     279struct WasmBoundsCheckCustom : public CommonCustomBase<WasmBoundsCheckCustom> {
     280    template<typename Func>
     281    static void forEachArg(Inst& inst, const Func& functor)
     282    {
     283        functor(inst.args[0], Arg::Use, Arg::GP, Arg::Width64);
     284        functor(inst.args[1], Arg::Use, Arg::GP, Arg::Width64);
     285    }
     286
     287    template<typename... Arguments>
     288    static bool isValidFormStatic(Arguments...)
     289    {
     290        return false;
     291    }
     292
     293    static bool isValidForm(Inst&);
     294
     295    static bool admitsStack(Inst&, unsigned)
     296    {
     297        return false;
     298    }
     299
     300    static bool isTerminal(Inst&)
     301    {
     302        return false;
     303    }
     304   
     305    static bool hasNonArgNonControlEffects(Inst&)
     306    {
     307        return true;
     308    }
     309
     310    static CCallHelpers::Jump generate(Inst& inst, CCallHelpers& jit, GenerationContext& context)
     311    {
     312        WasmBoundsCheckValue* value = inst.origin->as<WasmBoundsCheckValue>();
     313        CCallHelpers::Jump outOfBounds = Inst(Air::Branch64, value, Arg::relCond(CCallHelpers::AboveOrEqual), inst.args[0], inst.args[1]).generate(jit, context);
     314
     315        context.latePaths.append(createSharedTask<GenerationContext::LatePathFunction>(
     316            [=] (CCallHelpers& jit, Air::GenerationContext&) {
     317                outOfBounds.link(&jit);
     318                context.code->wasmBoundsCheckGenerator()->run(jit, value->pinnedGPR(), value->offset());
     319            }));
     320
     321        // We said we were not a terminal.
     322        return CCallHelpers::Jump();
     323    }
     324};
     325
    276326} } } // namespace JSC::B3::Air
    277327
  • trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes

    r207039 r207266  
    890890custom ColdCCall
    891891
    892 
     892# This is a special wasm opcode that branches to a trap handler. This uses the generator located to Air::Code
     893# to produce the side-exit code.
     894custom WasmBoundsCheck
     895
  • trunk/Source/JavaScriptCore/b3/testb3.cpp

    r207164 r207266  
    5555#include "B3ValueInlines.h"
    5656#include "B3VariableValue.h"
     57#include "B3WasmBoundsCheckValue.h"
    5758#include "CCallHelpers.h"
    5859#include "FPRInfo.h"
     
    1372813729    }
    1372913730    CHECK(found);
     13731}
     13732
     13733void testWasmBoundsCheck(unsigned offset)
     13734{
     13735    Procedure proc;
     13736    GPRReg pinned = GPRInfo::argumentGPR1;
     13737    proc.pinRegister(pinned);
     13738
     13739    proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR, unsigned actualOffset) {
     13740        CHECK_EQ(pinnedGPR, pinned);
     13741        CHECK_EQ(actualOffset, offset);
     13742
     13743        // This should always work because a function this simple should never have callee
     13744        // saves.
     13745        jit.move(CCallHelpers::TrustedImm32(42), GPRInfo::returnValueGPR);
     13746        jit.emitFunctionEpilogue();
     13747        jit.ret();
     13748    });
     13749
     13750    BasicBlock* root = proc.addBlock();
     13751    Value* left = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
     13752    if (pointerType() != Int32)
     13753        left = root->appendNew<Value>(proc, Trunc, Origin(), left);
     13754    root->appendNew<WasmBoundsCheckValue>(proc, Origin(), left, pinned, offset);
     13755    Value* result = root->appendNew<Const32Value>(proc, Origin(), 0x42);
     13756    root->appendNewControlValue(proc, Return, Origin(), result);
     13757
     13758    auto code = compile(proc);
     13759    CHECK_EQ(invoke<int32_t>(*code, 1, 2 + offset), 0x42);
     13760    CHECK_EQ(invoke<int32_t>(*code, 3, 2 + offset), 42);
     13761    CHECK_EQ(invoke<int32_t>(*code, 2, 2 + offset), 42);
    1373013762}
    1373113763
     
    1514915181    RUN(testPatchpointTerminalReturnValue(true));
    1515015182    RUN(testPatchpointTerminalReturnValue(false));
    15151    
     15183
    1515215184    RUN(testMemoryFence());
    1515315185    RUN(testStoreFence());
     
    1516915201    RUN(testLoadBaseIndexShift32());
    1517015202    RUN(testOptimizeMaterialization());
    15171    
     15203
     15204    RUN(testWasmBoundsCheck(0));
     15205    RUN(testWasmBoundsCheck(100));
     15206    RUN(testWasmBoundsCheck(10000));
     15207    RUN(testWasmBoundsCheck(std::numeric_limits<unsigned>::max() - 5));
     15208
    1517215209    if (isX86()) {
    1517315210        RUN(testBranchBitAndImmFusion(Identity, Int64, 1, Air::BranchTest32, Air::Arg::Tmp));
  • trunk/Websites/webkit.org/ChangeLog

    r206973 r207266  
     12016-10-12  Keith Miller  <keith_miller@apple.com>
     2
     3        B3 needs a special WasmBoundsCheck Opcode
     4        https://bugs.webkit.org/show_bug.cgi?id=163246
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Update the docs for the new WasmBoundsCheck opcode.
     9
     10        * docs/b3/intermediate-representation.html:
     11
    1122016-10-09  Simon Fraser  <simon.fraser@apple.com>
    213
  • trunk/Websites/webkit.org/docs/b3/intermediate-representation.html

    r206739 r207266  
    537537        to an instruction that branches to the exit if @a &gt;= @b or if either @a or @b are
    538538        NaN.  Must use the CheckValue class.</dd>
     539
     540      <dt>Void WasmBoundsCheck(Int32, pinnedGPR, offset)</dt>
     541      <dd>Special Wasm opcode. This branches on the first child. If the first child plus the offset
     542        produces a Int64 less than to the pinnedGPR this falls through. Otherwise, it branches to
     543        the exit path generated by the passed generator. Unlike the Patch/Check family, the
     544        generator used by WasmBoundsCheck sould be set on the Procuder itself. The GRPReg passed in
     545        pinnedGPR must also be marked as pinned by calling the Procedure's pinning API. B3 assumes
     546        the WasmBoundsCheck will side-exit when the it branches, so the generator must do some kind
     547        of termination. In Wasm this is used to trap and unwind back to JS. Must use the
     548        WasmBoundsCheckValue class.</dd>
    539549
    540550      <dt>Void Upsilon(T, ^phi)</dt>
Note: See TracChangeset for help on using the changeset viewer.