Changeset 215407 in webkit
- Timestamp:
- Apr 17, 2017 1:24:48 AM (7 years ago)
- Location:
- trunk/Source
- Files:
-
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r215405 r215407 1 2017-04-17 JF Bastien <jfbastien@apple.com> 2 3 B3: don't allow unsigned offsets in Value 4 https://bugs.webkit.org/show_bug.cgi?id=170692 5 6 Reviewed by Filip Pizlo. 7 8 MemoryValue and similar B3 opcode classes always expects a signed 9 offset. Giving it an out-of-bounds unsigned offset causes 10 implementation-defined behavior, which can cause badness as I just 11 fixed in WebAssembly. This patch makes it impossible to create a 12 Value opcodes with an unsigned value, or with an overly-large 13 value. 14 15 * b3/B3AtomicValue.cpp: 16 (JSC::B3::AtomicValue::AtomicValue): 17 * b3/B3AtomicValue.h: 18 * b3/B3Common.h: 19 (JSC::B3::isRepresentableAs): 20 * b3/B3EliminateCommonSubexpressions.cpp: 21 * b3/B3LowerToAir.cpp: 22 (JSC::B3::Air::LowerToAir::scaleForShl): 23 (JSC::B3::Air::LowerToAir::effectiveAddr): 24 (JSC::B3::Air::LowerToAir::addr): 25 (JSC::B3::Air::LowerToAir::tryAppendLea): 26 * b3/B3MemoryValue.cpp: 27 (JSC::B3::MemoryValue::isLegalOffsetImpl): 28 (JSC::B3::MemoryValue::MemoryValue): 29 * b3/B3MemoryValue.h: 30 * b3/B3MemoryValueInlines.h: 31 (JSC::B3::MemoryValue::isLegalOffsetImpl): 32 * b3/B3MoveConstants.cpp: 33 * b3/B3ReduceStrength.cpp: 34 * b3/B3StackmapSpecial.cpp: 35 (JSC::B3::StackmapSpecial::repForArg): 36 * b3/B3Value.h: 37 * b3/air/AirArg.cpp: 38 (JSC::B3::Air::Arg::stackAddrImpl): 39 * b3/air/AirArg.h: 40 (JSC::B3::Air::Arg::addr): 41 (JSC::B3::Air::Arg::stack): 42 (JSC::B3::Air::Arg::callArg): 43 (JSC::B3::Air::Arg::stackAddr): 44 (JSC::B3::Air::Arg::index): 45 (JSC::B3::Air::Arg::offset): 46 (JSC::B3::Air::Arg::isValidAddrForm): 47 (JSC::B3::Air::Arg::isValidIndexForm): 48 (JSC::B3::Air::Arg::asTrustedImm32): 49 (JSC::B3::Air::Arg::asAddress): 50 (JSC::B3::Air::Arg::asBaseIndex): 51 * b3/air/AirLowerStackArgs.cpp: 52 (JSC::B3::Air::lowerStackArgs): 53 * b3/testb3.cpp: 54 (JSC::B3::testMulArgStore): 55 (JSC::B3::testStore32): 56 (JSC::B3::testStoreConstant): 57 (JSC::B3::testStoreConstantPtr): 58 (JSC::B3::testStoreAddLoad32): 59 (JSC::B3::testStoreAddLoadImm32): 60 (JSC::B3::testStoreAddLoad8): 61 (JSC::B3::testStoreAddLoadImm8): 62 (JSC::B3::testStoreAddLoad16): 63 (JSC::B3::testStoreAddLoadImm16): 64 (JSC::B3::testStoreAddLoad64): 65 (JSC::B3::testStoreAddLoadImm64): 66 (JSC::B3::testStoreAddLoad32Index): 67 (JSC::B3::testStoreAddLoadImm32Index): 68 (JSC::B3::testStoreAddLoad64Index): 69 (JSC::B3::testStoreAddLoadImm64Index): 70 (JSC::B3::testStoreSubLoad): 71 (JSC::B3::testStoreAddLoadInterference): 72 (JSC::B3::testStoreAddAndLoad): 73 (JSC::B3::testStoreNegLoad32): 74 (JSC::B3::testStoreNegLoadPtr): 75 (JSC::B3::testLoadOffset): 76 (JSC::B3::testLoadOffsetNotConstant): 77 (JSC::B3::testLoadOffsetUsingAdd): 78 (JSC::B3::testLoadOffsetUsingAddInterference): 79 (JSC::B3::testLoadOffsetUsingAddNotConstant): 80 (JSC::B3::testStoreLoadStackSlot): 81 (JSC::B3::testLoad): 82 (JSC::B3::testInterpreter): 83 (JSC::B3::testTrappingStore): 84 (JSC::B3::testTrappingLoadAddStore): 85 (JSC::B3::testWasmAddress): 86 * wasm/WasmB3IRGenerator.cpp: 87 (JSC::Wasm::B3IRGenerator::fixupPointerPlusOffset): 88 (JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer): 89 (JSC::Wasm::B3IRGenerator::emitLoadOp): 90 (JSC::Wasm::B3IRGenerator::emitStoreOp): 91 1 92 2017-04-16 Joseph Pecoraro <pecoraro@apple.com> 2 93 -
trunk/Source/JavaScriptCore/b3/B3AtomicValue.cpp
r213714 r215407 47 47 } 48 48 49 AtomicValue::AtomicValue( Kind kind, Origin origin, Width width, Value* operand, Value* pointer, int32_toffset, HeapRange range, HeapRange fenceRange)49 AtomicValue::AtomicValue(AtomicValue::AtomicValueRMW, Kind kind, Origin origin, Width width, Value* operand, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange) 50 50 : MemoryValue(CheckedOpcode, kind, operand->type(), origin, offset, range, fenceRange, operand, pointer) 51 51 , m_width(width) … … 66 66 } 67 67 68 AtomicValue::AtomicValue( Kind kind, Origin origin, Width width, Value* expectedValue, Value* newValue, Value* pointer, int32_toffset, HeapRange range, HeapRange fenceRange)68 AtomicValue::AtomicValue(AtomicValue::AtomicValueCAS, Kind kind, Origin origin, Width width, Value* expectedValue, Value* newValue, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange) 69 69 : MemoryValue(CheckedOpcode, kind, kind.opcode() == AtomicWeakCAS ? Int32 : expectedValue->type(), origin, offset, range, fenceRange, expectedValue, newValue, pointer) 70 70 , m_width(width) -
trunk/Source/JavaScriptCore/b3/B3AtomicValue.h
r213714 r215407 53 53 private: 54 54 friend class Procedure; 55 56 AtomicValue(Kind, Origin, Width, Value* operand, Value* pointer, int32_t offset = 0, HeapRange range = HeapRange::top(), HeapRange fenceRange = HeapRange::top()); 57 58 AtomicValue(Kind, Origin, Width, Value* expectedValue, Value* newValue, Value* pointer, int32_t offset = 0, HeapRange range = HeapRange::top(), HeapRange fenceRange = HeapRange::top()); 59 55 56 enum AtomicValueRMW { AtomicValueRMWTag }; 57 enum AtomicValueCAS { AtomicValueCASTag }; 58 59 AtomicValue(Kind kind, Origin origin, Width width, Value* operand, Value* pointer) 60 : AtomicValue(kind, origin, width, operand, pointer, 0) 61 { 62 } 63 template<typename Int, 64 typename = typename std::enable_if<std::is_integral<Int>::value>::type, 65 typename = typename std::enable_if<std::is_signed<Int>::value>::type, 66 typename = typename std::enable_if<sizeof(Int) <= sizeof(OffsetType)>::type 67 > 68 AtomicValue(Kind kind, Origin origin, Width width, Value* operand, Value* pointer, Int offset, HeapRange range = HeapRange::top(), HeapRange fenceRange = HeapRange::top()) 69 : AtomicValue(AtomicValueRMWTag, kind, origin, width, operand, pointer, offset, range, fenceRange) 70 { 71 } 72 73 AtomicValue(Kind kind, Origin origin, Width width, Value* expectedValue, Value* newValue, Value* pointer) 74 : AtomicValue(kind, origin, width, expectedValue, newValue, pointer, 0) 75 { 76 } 77 template<typename Int, 78 typename = typename std::enable_if<std::is_integral<Int>::value>::type, 79 typename = typename std::enable_if<std::is_signed<Int>::value>::type, 80 typename = typename std::enable_if<sizeof(Int) <= sizeof(OffsetType)>::type 81 > 82 AtomicValue(Kind kind, Origin origin, Width width, Value* expectedValue, Value* newValue, Value* pointer, Int offset, HeapRange range = HeapRange::top(), HeapRange fenceRange = HeapRange::top()) 83 : AtomicValue(AtomicValueCASTag, kind, origin, width, expectedValue, newValue, pointer, offset, range, fenceRange) 84 { 85 } 86 87 // The above templates forward to these implementations. 88 AtomicValue(AtomicValueRMW, Kind, Origin, Width, Value* operand, Value* pointer, OffsetType, HeapRange = HeapRange::top(), HeapRange fenceRange = HeapRange::top()); 89 AtomicValue(AtomicValueCAS, Kind, Origin, Width, Value* expectedValue, Value* newValue, Value* pointer, OffsetType, HeapRange = HeapRange::top(), HeapRange fenceRange = HeapRange::top()); 90 60 91 Width m_width; 61 92 }; … … 64 95 65 96 #endif // ENABLE(B3_JIT) 66 -
trunk/Source/JavaScriptCore/b3/B3Common.h
r214636 r215407 103 103 104 104 template<typename ResultType> 105 inline bool isRepresentableAs(size_t value) 106 { 107 return isRepresentableAsImpl<ResultType, size_t, size_t>(value); 108 } 109 110 template<typename ResultType> 105 111 inline bool isRepresentableAs(double value) 106 112 { -
trunk/Source/JavaScriptCore/b3/B3EliminateCommonSubexpressions.cpp
r214636 r215407 258 258 Value* ptr = memory->lastChild(); 259 259 HeapRange range = memory->range(); 260 int32_toffset = memory->offset();260 Value::OffsetType offset = memory->offset(); 261 261 262 262 switch (memory->opcode()) { … … 306 306 Value* ptr = memory->lastChild(); 307 307 HeapRange range = memory->range(); 308 int32_toffset = memory->offset();308 Value::OffsetType offset = memory->offset(); 309 309 Type type = memory->type(); 310 310 -
trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp
r215340 r215407 440 440 return true; 441 441 } 442 443 std::optional<unsigned> scaleForShl(Value* shl, int32_t offset, std::optional<Width> width = std::nullopt) 442 443 template<typename Int, typename = Value::IsLegalOffset<Int>> 444 std::optional<unsigned> scaleForShl(Value* shl, Int offset, std::optional<Width> width = std::nullopt) 444 445 { 445 446 if (shl->opcode() != Shl) … … 464 465 465 466 // This turns the given operand into an address. 466 Arg effectiveAddr(Value* address, int32_t offset, Width width) 467 template<typename Int, typename = Value::IsLegalOffset<Int>> 468 Arg effectiveAddr(Value* address, Int offset, Width width) 467 469 { 468 470 ASSERT(Arg::isValidAddrForm(offset, width)); … … 553 555 return Arg::simpleAddr(tmp(value->lastChild())); 554 556 555 int32_toffset = value->offset();557 Value::OffsetType offset = value->offset(); 556 558 Width width = value->accessWidth(); 557 559 … … 2024 2026 // Add(@x, Shl(@y, $c)) 2025 2027 // Add(@x, @y) (only if offset != 0) 2026 int32_toffset = 0;2027 if (value->child(1)->isRepresentableAs< int32_t>()2028 Value::OffsetType offset = 0; 2029 if (value->child(1)->isRepresentableAs<Value::OffsetType>() 2028 2030 && canBeInternal(value->child(0)) 2029 2031 && value->child(0)->opcode() == Add) { 2030 2032 innerAdd = value->child(0); 2031 offset = static_cast< int32_t>(value->child(1)->asInt());2033 offset = static_cast<Value::OffsetType>(value->child(1)->asInt()); 2032 2034 value = value->child(0); 2033 2035 } -
trunk/Source/JavaScriptCore/b3/B3MemoryValue.cpp
r213714 r215407 39 39 } 40 40 41 bool MemoryValue::isLegalOffset (int64_t offset) const41 bool MemoryValue::isLegalOffsetImpl(int64_t offset) const 42 42 { 43 return B3::isRepresentableAs< int32_t>(offset) && isLegalOffset(static_cast<int32_t>(offset));43 return B3::isRepresentableAs<OffsetType>(offset) && isLegalOffset(static_cast<OffsetType>(offset)); 44 44 } 45 45 … … 81 81 // Use this form for Load (but not Load8Z, Load8S, or any of the Loads that have a suffix that 82 82 // describes the returned type). 83 MemoryValue::MemoryValue( Kind kind, Type type, Origin origin, Value* pointer, int32_toffset, HeapRange range, HeapRange fenceRange)83 MemoryValue::MemoryValue(MemoryValue::MemoryValueLoad, Kind kind, Type type, Origin origin, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange) 84 84 : Value(CheckedOpcode, kind, type, origin, pointer) 85 85 , m_offset(offset) … … 109 109 110 110 // Use this form for loads where the return type is implied. 111 MemoryValue::MemoryValue( Kind kind, Origin origin, Value* pointer, int32_toffset, HeapRange range, HeapRange fenceRange)111 MemoryValue::MemoryValue(MemoryValue::MemoryValueLoadImplied, Kind kind, Origin origin, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange) 112 112 : MemoryValue(kind, Int32, origin, pointer, offset, range, fenceRange) 113 113 { … … 126 126 127 127 // Use this form for stores. 128 MemoryValue::MemoryValue( Kind kind, Origin origin, Value* value, Value* pointer, int32_toffset, HeapRange range, HeapRange fenceRange)128 MemoryValue::MemoryValue(MemoryValue::MemoryValueStore, Kind kind, Origin origin, Value* value, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange) 129 129 : Value(CheckedOpcode, kind, Void, origin, value, pointer) 130 130 , m_offset(offset) -
trunk/Source/JavaScriptCore/b3/B3MemoryValue.h
r213714 r215407 32 32 #include "B3HeapRange.h" 33 33 #include "B3Value.h" 34 #include <type_traits> 34 35 35 36 namespace JSC { namespace B3 { … … 44 45 ~MemoryValue(); 45 46 46 int32_t offset() const { return m_offset; } 47 void setOffset(int32_t offset) { m_offset = offset; } 48 47 OffsetType offset() const { return m_offset; } 48 template<typename Int, typename = IsLegalOffset<Int>> 49 void setOffset(Int offset) { m_offset = offset; } 50 49 51 // You don't have to worry about using legal offsets unless you've entered quirks mode. 50 bool isLegalOffset(int32_t offset) const; 51 bool isLegalOffset(int64_t offset) const; 52 52 template<typename Int, 53 typename = typename std::enable_if<std::is_integral<Int>::value>::type, 54 typename = typename std::enable_if<std::is_signed<Int>::value>::type 55 > 56 bool isLegalOffset(Int offset) const { return isLegalOffsetImpl(offset); } 57 53 58 // A necessary consequence of MemoryValue having an offset is that it participates in instruction 54 59 // selection. This tells you if this will get lowered to something that requires an offsetless … … 85 90 Value* cloneImpl() const override; 86 91 87 template<typename ... Arguments>88 MemoryValue(CheckedOpcodeTag, Kind kind, Type type, Origin origin, int32_t offset, HeapRange range, HeapRange fenceRange, Arguments... arguments)92 template<typename Int, typename = IsLegalOffset<Int>, typename... Arguments> 93 MemoryValue(CheckedOpcodeTag, Kind kind, Type type, Origin origin, Int offset, HeapRange range, HeapRange fenceRange, Arguments... arguments) 89 94 : Value(CheckedOpcode, kind, type, origin, arguments...) 90 95 , m_offset(offset) … … 96 101 private: 97 102 friend class Procedure; 98 103 104 bool isLegalOffsetImpl(int32_t offset) const; 105 bool isLegalOffsetImpl(int64_t offset) const; 106 107 enum MemoryValueLoad { MemoryValueLoadTag }; 108 enum MemoryValueLoadImplied { MemoryValueLoadImpliedTag }; 109 enum MemoryValueStore { MemoryValueStoreTag }; 110 99 111 // Use this form for Load (but not Load8Z, Load8S, or any of the Loads that have a suffix that 100 112 // describes the returned type). 101 MemoryValue(Kind, Type, Origin, Value* pointer, int32_t offset = 0, HeapRange range = HeapRange::top(), HeapRange fenceRange = HeapRange()); 113 MemoryValue(Kind kind, Type type, Origin origin, Value* pointer) 114 : MemoryValue(MemoryValueLoadTag, kind, type, origin, pointer) 115 { 116 } 117 template<typename Int, typename = IsLegalOffset<Int>> 118 MemoryValue(Kind kind, Type type, Origin origin, Value* pointer, Int offset, HeapRange range = HeapRange::top(), HeapRange fenceRange = HeapRange()) 119 : MemoryValue(MemoryValueLoadTag, kind, type, origin, pointer, offset, range, fenceRange) 120 { 121 } 102 122 103 123 // Use this form for loads where the return type is implied. 104 MemoryValue(Kind, Origin, Value* pointer, int32_t offset = 0, HeapRange range = HeapRange::top(), HeapRange fenceRange = HeapRange()); 124 MemoryValue(Kind kind, Origin origin, Value* pointer) 125 : MemoryValue(MemoryValueLoadImpliedTag, kind, origin, pointer) 126 { 127 } 128 template<typename Int, typename = IsLegalOffset<Int>> 129 MemoryValue(Kind kind, Origin origin, Value* pointer, Int offset, HeapRange range = HeapRange::top(), HeapRange fenceRange = HeapRange()) 130 : MemoryValue(MemoryValueLoadImpliedTag, kind, origin, pointer, offset, range, fenceRange) 131 { 132 } 105 133 106 134 // Use this form for stores. 107 MemoryValue(Kind, Origin, Value* value, Value* pointer, int32_t offset = 0, HeapRange range = HeapRange::top(), HeapRange fenceRange = HeapRange()); 108 109 int32_t m_offset { 0 }; 135 MemoryValue(Kind kind, Origin origin, Value* value, Value* pointer) 136 : MemoryValue(MemoryValueStoreTag, kind, origin, value, pointer) 137 { 138 } 139 template<typename Int, typename = IsLegalOffset<Int>> 140 MemoryValue(Kind kind, Origin origin, Value* value, Value* pointer, Int offset, HeapRange range = HeapRange::top(), HeapRange fenceRange = HeapRange()) 141 : MemoryValue(MemoryValueStoreTag, kind, origin, value, pointer, offset, range, fenceRange) 142 { 143 } 144 145 // The above templates forward to these implementations. 146 MemoryValue(MemoryValueLoad, Kind, Type, Origin, Value* pointer, OffsetType = 0, HeapRange = HeapRange::top(), HeapRange fenceRange = HeapRange()); 147 MemoryValue(MemoryValueLoadImplied, Kind, Origin, Value* pointer, OffsetType = 0, HeapRange = HeapRange::top(), HeapRange fenceRange = HeapRange()); 148 MemoryValue(MemoryValueStore, Kind, Origin, Value*, Value* pointer, OffsetType = 0, HeapRange = HeapRange::top(), HeapRange fenceRange = HeapRange()); 149 150 OffsetType m_offset { 0 }; 110 151 HeapRange m_range { HeapRange::top() }; 111 152 HeapRange m_fenceRange { HeapRange() }; -
trunk/Source/JavaScriptCore/b3/B3MemoryValueInlines.h
r213714 r215407 33 33 namespace JSC { namespace B3 { 34 34 35 inline bool MemoryValue::isLegalOffset (int32_t offset) const35 inline bool MemoryValue::isLegalOffsetImpl(int32_t offset) const 36 36 { 37 37 // NOTE: This is inline because it constant-folds to true on x86! -
trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp
r214636 r215407 210 210 if (bestPointer) { 211 211 memoryValue->lastChild() = bestPointer; 212 memoryValue->setOffset( desiredOffset(bestPointer));212 memoryValue->setOffset(static_cast<int32_t>(desiredOffset(bestPointer))); 213 213 } 214 214 } … … 309 309 continue; 310 310 311 auto offset = sizeof(int64_t) * m_constTable.get(key); 312 if (!isRepresentableAs<Value::OffsetType>(offset)) 313 continue; 314 311 315 Value* tableBase = m_insertionSet.insertIntConstant( 312 316 valueIndex, value->origin(), pointerType(), … … 314 318 Value* result = m_insertionSet.insert<MemoryValue>( 315 319 valueIndex, Load, value->type(), value->origin(), tableBase, 316 s izeof(int64_t) * m_constTable.get(key));320 static_cast<Value::OffsetType>(offset)); 317 321 value->replaceWithIdentity(result); 318 322 } -
trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp
r215057 r215407 1556 1556 if (!sumOverflows<intptr_t>(offset, memory->offset())) { 1557 1557 offset += memory->offset(); 1558 int32_t smallOffset = static_cast<int32_t>(offset);1558 Value::OffsetType smallOffset = static_cast<Value::OffsetType>(offset); 1559 1559 if (smallOffset == offset) { 1560 1560 address = address->child(0); -
trunk/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp
r212970 r215407 271 271 return ValueRep::stack(arg.offset()); 272 272 ASSERT(arg.base() == Tmp(MacroAssembler::stackPointerRegister)); 273 return ValueRep::stack(arg.offset() - s tatic_cast<int32_t>(code.frameSize()));273 return ValueRep::stack(arg.offset() - safeCast<Value::OffsetType>(code.frameSize())); 274 274 default: 275 275 ASSERT_NOT_REACHED(); -
trunk/Source/JavaScriptCore/b3/B3Value.h
r213714 r215407 40 40 #include <wtf/FastMalloc.h> 41 41 #include <wtf/Noncopyable.h> 42 #include <wtf/StdLibExtras.h> 42 43 #include <wtf/TriState.h> 43 44 … … 283 284 template<typename Functor> 284 285 void walk(const Functor& functor, PhiChildren* = nullptr); 286 287 // B3 purposefully only represents signed 32-bit offsets because that's what x86 can encode, and 288 // ARM64 cannot encode anything bigger. The IsLegalOffset type trait is then used on B3 Value 289 // methods to prevent implicit conversions by C++ from invalid offset types: these cause compilation 290 // to fail, instead of causing implementation-defined behavior (which often turns to exploit). 291 // OffsetType isn't sufficient to determine offset validity! Each Value opcode further has an 292 // isLegalOffset runtime method used to determine value legality at runtime. This is exposed to users 293 // of B3 to force them to reason about the target's offset. 294 typedef int32_t OffsetType; 295 template<typename Int> 296 struct IsLegalOffset : std::conjunction< 297 typename std::enable_if<std::is_integral<Int>::value>::type, 298 typename std::enable_if<std::is_signed<Int>::value>::type, 299 typename std::enable_if<sizeof(Int) <= sizeof(OffsetType)>::type 300 > { }; 301 285 302 286 303 protected: -
trunk/Source/JavaScriptCore/b3/air/AirArg.cpp
r215292 r215407 42 42 namespace JSC { namespace B3 { namespace Air { 43 43 44 Arg Arg::stackAddr (int32_t offsetFromFP, unsigned frameSize, Width width)44 Arg Arg::stackAddrImpl(int32_t offsetFromFP, unsigned frameSize, Width width) 45 45 { 46 46 Arg result = Arg::addr(Air::Tmp(GPRInfo::callFrameRegister), offsetFromFP); -
trunk/Source/JavaScriptCore/b3/air/AirArg.h
r215292 r215407 32 32 #include "B3Common.h" 33 33 #include "B3Type.h" 34 #include "B3Value.h" 34 35 #include "B3Width.h" 35 36 #include <wtf/Optional.h> … … 535 536 } 536 537 537 static Arg addr(Air::Tmp base, int32_t offset = 0) 538 template<typename Int, typename = Value::IsLegalOffset<Int>> 539 static Arg addr(Air::Tmp base, Int offset) 538 540 { 539 541 ASSERT(base.isGP()); … … 545 547 } 546 548 547 static Arg stack(StackSlot* value, int32_t offset = 0) 549 static Arg addr(Air::Tmp base) 550 { 551 return addr(base, 0); 552 } 553 554 template<typename Int, typename = Value::IsLegalOffset<Int>> 555 static Arg stack(StackSlot* value, Int offset) 548 556 { 549 557 Arg result; … … 554 562 } 555 563 556 static Arg callArg(int32_t offset) 564 static Arg stack(StackSlot* value) 565 { 566 return stack(value, 0); 567 } 568 569 template<typename Int, typename = Value::IsLegalOffset<Int>> 570 static Arg callArg(Int offset) 557 571 { 558 572 Arg result; … … 561 575 return result; 562 576 } 563 564 static Arg stackAddr(int32_t offsetFromFP, unsigned frameSize, Width); 577 578 template<typename Int, typename = Value::IsLegalOffset<Int>> 579 static Arg stackAddr(Int offsetFromFP, unsigned frameSize, Width width) 580 { 581 return stackAddrImpl(offsetFromFP, frameSize, width); 582 } 565 583 566 584 // If you don't pass a Width, this optimistically assumes that you're using the right width. … … 605 623 } 606 624 607 static Arg index(Air::Tmp base, Air::Tmp index, unsigned scale = 1, int32_t offset = 0) 625 template<typename Int, typename = Value::IsLegalOffset<Int>> 626 static Arg index(Air::Tmp base, Air::Tmp index, unsigned scale, Int offset) 608 627 { 609 628 ASSERT(base.isGP()); … … 617 636 result.m_offset = offset; 618 637 return result; 638 } 639 640 static Arg index(Air::Tmp base, Air::Tmp index, unsigned scale = 1) 641 { 642 return Arg::index(base, index, scale, 0); 619 643 } 620 644 … … 926 950 bool hasOffset() const { return isMemory(); } 927 951 928 int32_toffset() const952 Value::OffsetType offset() const 929 953 { 930 954 if (kind() == Stack) 931 return static_cast< int32_t>(m_scale);955 return static_cast<Value::OffsetType>(m_scale); 932 956 ASSERT(kind() == Addr || kind() == CallArg || kind() == Index); 933 return static_cast< int32_t>(m_offset);957 return static_cast<Value::OffsetType>(m_offset); 934 958 } 935 959 … … 1142 1166 } 1143 1167 1144 static bool isValidAddrForm(int32_t offset, std::optional<Width> width = std::nullopt) 1168 template<typename Int, typename = Value::IsLegalOffset<Int>> 1169 static bool isValidAddrForm(Int offset, std::optional<Width> width = std::nullopt) 1145 1170 { 1146 1171 if (isX86()) … … 1167 1192 } 1168 1193 1169 static bool isValidIndexForm(unsigned scale, int32_t offset, std::optional<Width> width = std::nullopt) 1194 template<typename Int, typename = Value::IsLegalOffset<Int>> 1195 static bool isValidIndexForm(unsigned scale, Int offset, std::optional<Width> width = std::nullopt) 1170 1196 { 1171 1197 if (!isValidScale(scale, width)) … … 1277 1303 { 1278 1304 ASSERT(isImm() || isBitImm()); 1279 return MacroAssembler::TrustedImm32(static_cast< int32_t>(m_offset));1305 return MacroAssembler::TrustedImm32(static_cast<Value::OffsetType>(m_offset)); 1280 1306 } 1281 1307 … … 1302 1328 return MacroAssembler::Address(m_base.gpr()); 1303 1329 ASSERT(isAddr()); 1304 return MacroAssembler::Address(m_base.gpr(), static_cast< int32_t>(m_offset));1330 return MacroAssembler::Address(m_base.gpr(), static_cast<Value::OffsetType>(m_offset)); 1305 1331 } 1306 1332 … … 1310 1336 return MacroAssembler::BaseIndex( 1311 1337 m_base.gpr(), m_index.gpr(), static_cast<MacroAssembler::Scale>(logScale()), 1312 static_cast< int32_t>(m_offset));1338 static_cast<Value::OffsetType>(m_offset)); 1313 1339 } 1314 1340 … … 1413 1439 1414 1440 private: 1441 static Arg stackAddrImpl(int32_t, unsigned, Width); 1442 1415 1443 int64_t m_offset { 0 }; 1416 1444 Kind m_kind { Invalid }; -
trunk/Source/JavaScriptCore/b3/air/AirLowerStackArgs.cpp
r215292 r215407 75 75 inst.forEachArg( 76 76 [&] (Arg& arg, Arg::Role role, Bank, Width width) { 77 auto stackAddr = [&] ( int32_toffset) -> Arg {77 auto stackAddr = [&] (Value::OffsetType offset) -> Arg { 78 78 Arg result = Arg::stackAddr(offset, code.frameSize(), width); 79 79 if (!result) { -
trunk/Source/JavaScriptCore/b3/testb3.cpp
r215340 r215407 880 880 root->appendNew<MemoryValue>( 881 881 proc, Store, Origin(), value, 882 root->appendNew<ConstPtrValue>(proc, Origin(), &valueSlot) );882 root->appendNew<ConstPtrValue>(proc, Origin(), &valueSlot), 0); 883 883 root->appendNew<MemoryValue>( 884 884 proc, Store, Origin(), mul, 885 root->appendNew<ConstPtrValue>(proc, Origin(), &mulSlot) );885 root->appendNew<ConstPtrValue>(proc, Origin(), &mulSlot), 0); 886 886 887 887 root->appendNewControlValue( … … 5422 5422 proc, Trunc, Origin(), 5423 5423 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), 5424 root->appendNew<ConstPtrValue>(proc, Origin(), &slot) );5424 root->appendNew<ConstPtrValue>(proc, Origin(), &slot), 0); 5425 5425 root->appendNewControlValue( 5426 5426 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); … … 5438 5438 proc, Store, Origin(), 5439 5439 root->appendNew<Const32Value>(proc, Origin(), value), 5440 root->appendNew<ConstPtrValue>(proc, Origin(), &slot) );5440 root->appendNew<ConstPtrValue>(proc, Origin(), &slot), 0); 5441 5441 root->appendNewControlValue( 5442 5442 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); … … 5458 5458 proc, Store, Origin(), 5459 5459 root->appendNew<ConstPtrValue>(proc, Origin(), value), 5460 root->appendNew<ConstPtrValue>(proc, Origin(), &slot) );5460 root->appendNew<ConstPtrValue>(proc, Origin(), &slot), 0); 5461 5461 root->appendNewControlValue( 5462 5462 proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0)); … … 5760 5760 proc, Trunc, Origin(), 5761 5761 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), 5762 slotPtr );5762 slotPtr, 0); 5763 5763 root->appendNewControlValue( 5764 5764 proc, Return, Origin(), … … 5810 5810 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr), 5811 5811 root->appendNew<Const32Value>(proc, Origin(), amount)), 5812 slotPtr );5812 slotPtr, 0); 5813 5813 root->appendNewControlValue( 5814 5814 proc, Return, Origin(), … … 5833 5833 proc, Trunc, Origin(), 5834 5834 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), 5835 slotPtr );5835 slotPtr, 0); 5836 5836 root->appendNewControlValue( 5837 5837 proc, Return, Origin(), … … 5922 5922 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr), 5923 5923 root->appendNew<Const32Value>(proc, Origin(), amount)), 5924 slotPtr );5924 slotPtr, 0); 5925 5925 root->appendNewControlValue( 5926 5926 proc, Return, Origin(), … … 5945 5945 proc, Trunc, Origin(), 5946 5946 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), 5947 slotPtr );5947 slotPtr, 0); 5948 5948 root->appendNewControlValue( 5949 5949 proc, Return, Origin(), … … 5995 5995 root->appendNew<MemoryValue>(proc, loadOpcode, Origin(), slotPtr), 5996 5996 root->appendNew<Const32Value>(proc, Origin(), amount)), 5997 slotPtr );5997 slotPtr, 0); 5998 5998 root->appendNewControlValue( 5999 5999 proc, Return, Origin(), … … 6016 6016 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr), 6017 6017 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), 6018 slotPtr );6018 slotPtr, 0); 6019 6019 root->appendNewControlValue( 6020 6020 proc, Return, Origin(), … … 6064 6064 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr), 6065 6065 root->appendNew<Const64Value>(proc, Origin(), amount)), 6066 slotPtr );6066 slotPtr, 0); 6067 6067 root->appendNewControlValue( 6068 6068 proc, Return, Origin(), … … 6096 6096 proc, Trunc, Origin(), 6097 6097 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), 6098 slotPtr );6098 slotPtr, 0); 6099 6099 root->appendNewControlValue( 6100 6100 proc, Return, Origin(), … … 6126 6126 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr), 6127 6127 root->appendNew<Const32Value>(proc, Origin(), amount)), 6128 slotPtr );6128 slotPtr, 0); 6129 6129 root->appendNewControlValue( 6130 6130 proc, Return, Origin(), … … 6280 6280 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr), 6281 6281 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), 6282 slotPtr );6282 slotPtr, 0); 6283 6283 root->appendNewControlValue( 6284 6284 proc, Return, Origin(), … … 6310 6310 root->appendNew<MemoryValue>(proc, Load, Int64, Origin(), slotPtr), 6311 6311 root->appendNew<Const64Value>(proc, Origin(), amount)), 6312 slotPtr );6312 slotPtr, 0); 6313 6313 root->appendNewControlValue( 6314 6314 proc, Return, Origin(), … … 6334 6334 proc, Trunc, Origin(), 6335 6335 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0))), 6336 slotPtr );6336 slotPtr, 0); 6337 6337 root->appendNewControlValue( 6338 6338 proc, Return, Origin(), … … 6355 6355 proc, Store, Origin(), 6356 6356 root->appendNew<Const32Value>(proc, Origin(), 666), 6357 otherSlotPtr );6357 otherSlotPtr, 0); 6358 6358 root->appendNew<MemoryValue>( 6359 6359 proc, Store, Origin(), … … 6361 6361 proc, Add, Origin(), 6362 6362 load, root->appendNew<Const32Value>(proc, Origin(), amount)), 6363 slotPtr );6363 slotPtr, 0); 6364 6364 root->appendNewControlValue( 6365 6365 proc, Return, Origin(), … … 6385 6385 root->appendNew<Const32Value>(proc, Origin(), amount)), 6386 6386 root->appendNew<Const32Value>(proc, Origin(), mask)), 6387 slotPtr );6387 slotPtr, 0); 6388 6388 root->appendNewControlValue( 6389 6389 proc, Return, Origin(), … … 6409 6409 root->appendNew<Const32Value>(proc, Origin(), 0), 6410 6410 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), slotPtr)), 6411 slotPtr );6411 slotPtr, 0); 6412 6412 6413 6413 root->appendNewControlValue( … … 6433 6433 root->appendNew<ConstPtrValue>(proc, Origin(), 0), 6434 6434 root->appendNew<MemoryValue>(proc, Load, pointerType(), Origin(), slotPtr)), 6435 slotPtr );6435 slotPtr, 0); 6436 6436 6437 6437 root->appendNewControlValue( … … 6469 6469 proc, Add, Origin(), 6470 6470 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0), 6471 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, s izeof(int))));6471 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, static_cast<int32_t>(sizeof(int))))); 6472 6472 6473 6473 CHECK(compileAndRun<int>(proc) == array[0] + array[1]); … … 6485 6485 proc, Add, Origin(), 6486 6486 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, 0), 6487 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, s izeof(int))));6487 root->appendNew<MemoryValue>(proc, Load, Int32, Origin(), arrayPtr, static_cast<int32_t>(sizeof(int))))); 6488 6488 6489 6489 CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]); … … 6509 6509 root->appendNew<Value>( 6510 6510 proc, Add, Origin(), arrayPtr, 6511 root->appendNew<ConstPtrValue>(proc, Origin(), s izeof(int))))));6511 root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int))))))); 6512 6512 6513 6513 CHECK(compileAndRun<int>(proc) == array[0] + array[1]); … … 6532 6532 root->appendNew<Value>( 6533 6533 proc, Add, Origin(), arrayPtr, 6534 root->appendNew<ConstPtrValue>(proc, Origin(), s izeof(int))));6534 root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int))))); 6535 6535 root->appendNew<MemoryValue>( 6536 6536 proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, 0); 6537 6537 root->appendNew<MemoryValue>( 6538 proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, s izeof(int));6538 proc, Store, Origin(), theNumberOfTheBeast, otherArrayPtr, static_cast<int32_t>(sizeof(int))); 6539 6539 root->appendNewControlValue( 6540 6540 proc, Return, Origin(), … … 6566 6566 root->appendNew<Value>( 6567 6567 proc, Add, Origin(), arrayPtr, 6568 root->appendNew<ConstPtrValue>(proc, Origin(), s izeof(int))))));6568 root->appendNew<ConstPtrValue>(proc, Origin(), static_cast<int32_t>(sizeof(int))))))); 6569 6569 6570 6570 CHECK(compileAndRun<int>(proc, &array[0]) == array[0] + array[1]); … … 6691 6691 proc, Trunc, Origin(), 6692 6692 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)), 6693 stack );6693 stack, 0); 6694 6694 6695 6695 root->appendNewControlValue( … … 6761 6761 proc, opcode, type, Origin(), 6762 6762 root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0), 6763 s izeof(InputType)));6763 static_cast<int32_t>(sizeof(InputType)))); 6764 6764 6765 6765 CHECK(isIdentical(compileAndRun<CType>(proc, &value - 1), modelLoad<CType>(value))); … … 12903 12903 proc, Mul, Origin(), 12904 12904 addToDataPointer->appendNew<MemoryValue>( 12905 proc, Load, pointerType(), Origin(), codePointerValue, s izeof(intptr_t)),12905 proc, Load, pointerType(), Origin(), codePointerValue, static_cast<int32_t>(sizeof(intptr_t))), 12906 12906 addToDataPointer->appendIntConstant( 12907 12907 proc, Origin(), pointerType(), sizeof(intptr_t))))); … … 12932 12932 proc, Mul, Origin(), 12933 12933 addToCodePointerTaken->appendNew<MemoryValue>( 12934 proc, Load, pointerType(), Origin(), codePointerValue, s izeof(intptr_t)),12934 proc, Load, pointerType(), Origin(), codePointerValue, static_cast<int32_t>(sizeof(intptr_t))), 12935 12935 addToCodePointerTaken->appendIntConstant( 12936 12936 proc, Origin(), pointerType(), sizeof(intptr_t))))); … … 12955 12955 proc, Load, pointerType(), Origin(), dataPointerValue), 12956 12956 addToData->appendNew<MemoryValue>( 12957 proc, Load, pointerType(), Origin(), codePointerValue, s izeof(intptr_t))),12957 proc, Load, pointerType(), Origin(), codePointerValue, static_cast<int32_t>(sizeof(intptr_t)))), 12958 12958 dataPointerValue); 12959 12959 addToData->appendNew<VariableValue>( … … 13876 13876 proc, trapping(Store), Origin(), 13877 13877 root->appendNew<Const32Value>(proc, Origin(), 111), 13878 root->appendNew<ConstPtrValue>(proc, Origin(), &x) );13878 root->appendNew<ConstPtrValue>(proc, Origin(), &x), 0); 13879 13879 Effects expectedEffects; 13880 13880 expectedEffects.exitsSideways = true; … … 13913 13913 root->appendNew<MemoryValue>(proc, trapping(Load), Int32, Origin(), ptr), 13914 13914 root->appendNew<Const32Value>(proc, Origin(), 3)), 13915 ptr );13915 ptr, 0); 13916 13916 root->appendNew<Value>(proc, Return, Origin()); 13917 13917 compileAndRun<int>(proc); … … 15229 15229 pointer = body->appendNew<Value>(proc, ZExt32, Origin(), pointer); 15230 15230 body->appendNew<MemoryValue>(proc, Store, Origin(), valueToStore, 15231 body->appendNew<WasmAddressValue>(proc, Origin(), pointer, pinnedGPR) );15231 body->appendNew<WasmAddressValue>(proc, Origin(), pointer, pinnedGPR), 0); 15232 15232 UpsilonValue* incUpsilon = body->appendNew<UpsilonValue>(proc, Origin(), 15233 15233 body->appendNew<Value>(proc, Add, Origin(), indexPhi, -
trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
r215379 r215407 61 61 #include "WasmThunks.h" 62 62 #include <wtf/Optional.h> 63 #include <wtf/StdLibExtras.h> 63 64 64 65 void dumpProcedure(void* ptr) … … 238 239 void emitChecksForModOrDiv(B3::Opcode, ExpressionType left, ExpressionType right); 239 240 240 void fixupPointerPlusOffset(ExpressionType&, uint32_t&);241 int32_t WARN_UNUSED_RETURN fixupPointerPlusOffset(ExpressionType&, uint32_t); 241 242 242 243 Value* materializeWasmContext(Procedure&, BasicBlock*); … … 262 263 263 264 // Memory accesses in WebAssembly have unsigned 32-bit offsets, whereas they have signed 32-bit offsets in B3. 264 void B3IRGenerator::fixupPointerPlusOffset(ExpressionType& ptr, uint32_t&offset)265 int32_t B3IRGenerator::fixupPointerPlusOffset(ExpressionType& ptr, uint32_t offset) 265 266 { 266 267 if (static_cast<uint64_t>(offset) > static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) { 267 268 ptr = m_currentBlock->appendNew<Value>(m_proc, Add, origin(), ptr, m_currentBlock->appendNew<Const64Value>(m_proc, origin(), offset)); 268 offset = 0; 269 } 269 return 0; 270 } 271 return offset; 270 272 } 271 273 … … 508 510 auto B3IRGenerator::addCurrentMemory(ExpressionType& result) -> PartialResult 509 511 { 510 Value* memoryObject = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfMemory());512 Value* memoryObject = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), m_instanceValue, safeCast<int32_t>(JSWebAssemblyInstance::offsetOfMemory())); 511 513 512 514 static_assert(sizeof(decltype(static_cast<JSWebAssemblyInstance*>(nullptr)->memory()->memory().size())) == sizeof(uint64_t), "codegen relies on this size"); 513 Value* size = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int64, origin(), memoryObject, JSWebAssemblyMemory::offsetOfSize());515 Value* size = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int64, origin(), memoryObject, safeCast<int32_t>(JSWebAssemblyMemory::offsetOfSize())); 514 516 515 517 constexpr uint32_t shiftValue = 16; … … 532 534 auto B3IRGenerator::getGlobal(uint32_t index, ExpressionType& result) -> PartialResult 533 535 { 534 Value* globalsArray = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfGlobals());535 result = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, toB3Type(m_info.globals[index].type), origin(), globalsArray, index * sizeof(Register));536 Value* globalsArray = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), m_instanceValue, safeCast<int32_t>(JSWebAssemblyInstance::offsetOfGlobals())); 537 result = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, toB3Type(m_info.globals[index].type), origin(), globalsArray, safeCast<int32_t>(index * sizeof(Register))); 536 538 return { }; 537 539 } … … 540 542 { 541 543 ASSERT(toB3Type(m_info.globals[index].type) == value->type()); 542 Value* globalsArray = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfGlobals());543 m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin(), value, globalsArray, index * sizeof(Register));544 Value* globalsArray = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), m_instanceValue, safeCast<int32_t>(JSWebAssemblyInstance::offsetOfGlobals())); 545 m_currentBlock->appendNew<MemoryValue>(m_proc, Store, origin(), value, globalsArray, safeCast<int32_t>(index * sizeof(Register))); 544 546 return { }; 545 547 } … … 556 558 break; 557 559 case MemoryMode::Signaling: 558 // We've virtually mapped 4GiB+redzone fo this memory. Only the user-allocated pages are addressable, contiguously in range [0, current], and everything above is mapped PROT_NONE. We don't need to perform any explicit bounds check in the 4GiB range because WebAssembly register memory accesses are 32-bit. However WebAssembly register+immediate accesses perform the addition in 64-bit which can push an access above the 32-bit limit. The redzone will catch most small immediates, and we'll explicitly bounds check any register + large immediate access.560 // We've virtually mapped 4GiB+redzone for this memory. Only the user-allocated pages are addressable, contiguously in range [0, current], and everything above is mapped PROT_NONE. We don't need to perform any explicit bounds check in the 4GiB range because WebAssembly register memory accesses are 32-bit. However WebAssembly register+immediate accesses perform the addition in 64-bit which can push an access above the 32-bit limit. The redzone will catch most small immediates, and we'll explicitly bounds check any register + large immediate access. 559 561 if (offset >= Memory::fastMappedRedzoneBytes()) 560 562 m_currentBlock->appendNew<WasmBoundsCheckValue>(m_proc, origin(), pointer, InvalidGPRReg, sizeOfOperation + offset - 1, m_info.memory.maximum()); … … 599 601 } 600 602 601 inline Value* B3IRGenerator::emitLoadOp(LoadOpType op, ExpressionType pointer, uint32_t offset)602 { 603 fixupPointerPlusOffset(pointer,offset);603 inline Value* B3IRGenerator::emitLoadOp(LoadOpType op, ExpressionType pointer, uint32_t uoffset) 604 { 605 int32_t offset = fixupPointerPlusOffset(pointer, uoffset); 604 606 605 607 switch (op) { … … 738 740 739 741 740 inline void B3IRGenerator::emitStoreOp(StoreOpType op, ExpressionType pointer, ExpressionType value, uint32_t offset)741 { 742 fixupPointerPlusOffset(pointer,offset);742 inline void B3IRGenerator::emitStoreOp(StoreOpType op, ExpressionType pointer, ExpressionType value, uint32_t uoffset) 743 { 744 int32_t offset = fixupPointerPlusOffset(pointer, uoffset); 743 745 744 746 switch (op) { … … 941 943 if (m_info.isImportedFunctionFromFunctionIndexSpace(functionIndex)) { 942 944 // FIXME imports can be linked here, instead of generating a patchpoint, because all import stubs are generated before B3 compilation starts. https://bugs.webkit.org/show_bug.cgi?id=166462 943 Value* functionImport = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfImportFunction(functionIndex));944 Value* jsTypeOfImport = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, origin(), functionImport, JSCell::typeInfoTypeOffset());945 Value* functionImport = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), m_instanceValue, safeCast<int32_t>(JSWebAssemblyInstance::offsetOfImportFunction(functionIndex))); 946 Value* jsTypeOfImport = m_currentBlock->appendNew<MemoryValue>(m_proc, Load8Z, origin(), functionImport, safeCast<int32_t>(JSCell::typeInfoTypeOffset())); 945 947 Value* isWasmCall = m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), jsTypeOfImport, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), WebAssemblyFunctionType)); 946 948 … … 972 974 // https://bugs.webkit.org/show_bug.cgi?id=170375 973 975 Value* codeBlock = isJSBlock->appendNew<MemoryValue>(m_proc, 974 Load, pointerType(), origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfCodeBlock());976 Load, pointerType(), origin(), m_instanceValue, safeCast<int32_t>(JSWebAssemblyInstance::offsetOfCodeBlock())); 975 977 Value* jumpDestination = isJSBlock->appendNew<MemoryValue>(m_proc, 976 Load, pointerType(), origin(), codeBlock, JSWebAssemblyCodeBlock::offsetOfImportWasmToJSStub(functionIndex));978 Load, pointerType(), origin(), codeBlock, safeCast<int32_t>(JSWebAssemblyCodeBlock::offsetOfImportWasmToJSStub(functionIndex))); 977 979 Value* jsCallResult = wasmCallingConvention().setupCall(m_proc, isJSBlock, origin(), args, toB3Type(returnType), 978 980 [&] (PatchpointValue* patchpoint) { … … 1030 1032 { 1031 1033 ExpressionType table = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), 1032 m_instanceValue, JSWebAssemblyInstance::offsetOfTable());1034 m_instanceValue, safeCast<int32_t>(JSWebAssemblyInstance::offsetOfTable())); 1033 1035 callableFunctionBuffer = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), 1034 table, JSWebAssemblyTable::offsetOfFunctions());1036 table, safeCast<int32_t>(JSWebAssemblyTable::offsetOfFunctions())); 1035 1037 callableFunctionBufferSize = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(), 1036 table, JSWebAssemblyTable::offsetOfSize());1038 table, safeCast<int32_t>(JSWebAssemblyTable::offsetOfSize())); 1037 1039 } 1038 1040 … … 1055 1057 // Check that the CallableFunction is initialized. We trap if it isn't. An "invalid" SignatureIndex indicates it's not initialized. 1056 1058 static_assert(sizeof(CallableFunction::signatureIndex) == sizeof(uint32_t), "Load codegen assumes i32"); 1057 ExpressionType calleeSignatureIndex = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(), callableFunction, OBJECT_OFFSETOF(CallableFunction, signatureIndex));1059 ExpressionType calleeSignatureIndex = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(), callableFunction, safeCast<int32_t>(OBJECT_OFFSETOF(CallableFunction, signatureIndex))); 1058 1060 { 1059 1061 CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(), … … 1078 1080 } 1079 1081 1080 ExpressionType calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), callableFunction, OBJECT_OFFSETOF(CallableFunction, code));1082 ExpressionType calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(), callableFunction, safeCast<int32_t>(OBJECT_OFFSETOF(CallableFunction, code))); 1081 1083 1082 1084 Type returnType = signature.returnType(); -
trunk/Source/WTF/ChangeLog
r215386 r215407 1 2017-04-17 JF Bastien <jfbastien@apple.com> 2 3 B3: don't allow unsigned offsets in Value 4 https://bugs.webkit.org/show_bug.cgi?id=170692 5 6 Reviewed by Filip Pizlo. 7 8 Add C++17's std::conjunction type trait, except for Microsoft VS 9 2015 update 2 and later because it adds the logical operator type 10 traits, event when C++ is pre-2017: 11 https://blogs.msdn.microsoft.com/vcblog/2016/01/22/vs-2015-update-2s-stl-is-c17-so-far-feature-complete/ 12 13 * wtf/StdLibExtras.h: 14 1 15 2017-04-14 Mark Lam <mark.lam@apple.com> 2 16 -
trunk/Source/WTF/wtf/StdLibExtras.h
r214409 r215407 31 31 #include <cstring> 32 32 #include <memory> 33 #include <type_traits> 33 34 #include <wtf/Assertions.h> 34 35 #include <wtf/CheckedArithmetic.h> … … 511 512 } 512 513 514 #if __cplusplus < 201703L && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER < 190023918) 515 template<class...> struct wtf_conjunction_impl; 516 template<> struct wtf_conjunction_impl<> : true_type { }; 517 template<class B0> struct wtf_conjunction_impl<B0> : B0 { }; 518 template<class B0, class B1> struct wtf_conjunction_impl<B0, B1> : conditional<B0::value, B1, B0>::type { }; 519 template<class B0, class B1, class B2, class... Bn> struct wtf_conjunction_impl<B0, B1, B2, Bn...> : conditional<B0::value, wtf_conjunction_impl<B1, B2, Bn...>, B0>::type { }; 520 template<class... _Args> struct conjunction : wtf_conjunction_impl<_Args...> { }; 521 #endif 522 513 523 } // namespace std 514 524
Note: See TracChangeset
for help on using the changeset viewer.