Ignore:
Timestamp:
Aug 31, 2011, 11:16:11 AM (14 years ago)
Author:
[email protected]
Message:

Add support for checked arithmetic
https://bugs.webkit.org/show_bug.cgi?id=67095

Reviewed by Sam Weinig.

../../../../Volumes/Data/git/WebKit/OpenSource/Source/JavaScriptCore:

Add a checked arithmetic class Checked<T> that provides overflow-safe
arithmetic over all integral types. Checked<T> supports addition, subtraction
and multiplication, along with "bool" conversions and equality operators.

Checked<> can be used in either CRASH() on overflow or delayed failure modes,
although the default is to CRASH().

To ensure the code is actually in use (rather than checking in dead code) I've
made a couple of properties in YARR use Checked<int> and Checked<unsigned>
instead of raw value arithmetic. This has resulted in a moderate set of changes,
to YARR - mostly adding .get() calls, but a couple of casts from unsigned long
to unsigned for some uses of sizeof, as Checked<> currently does not support
mixed signed-ness of types wider that 32 bits.

Happily the increased type safety of Checked<> means that it's not possible to
accidentally assign away precision, nor accidentally call integer overload of
a function instead of the bool version.

No measurable regression in performance, and SunSpider claims this patch to be
a progression of 0.3%.

(WTF::CrashOnOverflow::overflowed):
(WTF::CrashOnOverflow::clearOverflow):
(WTF::CrashOnOverflow::hasOverflowed):
(WTF::RecordOverflow::RecordOverflow):
(WTF::RecordOverflow::overflowed):
(WTF::RecordOverflow::clearOverflow):
(WTF::RecordOverflow::hasOverflowed):
(WTF::isInBounds):
(WTF::safeAdd):
(WTF::safeSub):
(WTF::safeMultiply):
(WTF::safeEquals):
(WTF::workAroundClangBug):
(WTF::Checked::Checked):
(WTF::Checked::operator=):
(WTF::Checked::operator++):
(WTF::Checked::operator--):
(WTF::Checked::operator!):
(WTF::Checked::operator UnspecifiedBoolType*):
(WTF::Checked::get):
(WTF::Checked::operator+=):
(WTF::Checked::operator-=):
(WTF::Checked::operator*=):
(WTF::Checked::operator==):
(WTF::Checked::operator!=):
(WTF::operator+):
(WTF::operator-):
(WTF::operator*):

  • yarr/YarrInterpreter.cpp:

(JSC::Yarr::ByteCompiler::atomPatternCharacter):
(JSC::Yarr::ByteCompiler::atomCharacterClass):
(JSC::Yarr::ByteCompiler::atomBackReference):
(JSC::Yarr::ByteCompiler::atomParentheticalAssertionEnd):
(JSC::Yarr::ByteCompiler::atomParenthesesSubpatternEnd):
(JSC::Yarr::ByteCompiler::atomParenthesesOnceEnd):
(JSC::Yarr::ByteCompiler::atomParenthesesTerminalEnd):

  • yarr/YarrInterpreter.h:

(JSC::Yarr::ByteTerm::ByteTerm):
(JSC::Yarr::ByteTerm::CheckInput):
(JSC::Yarr::ByteTerm::UncheckInput):

  • yarr/YarrJIT.cpp:

(JSC::Yarr::YarrGenerator::generateAssertionEOL):
(JSC::Yarr::YarrGenerator::generatePatternCharacterFixed):
(JSC::Yarr::YarrGenerator::generatePatternCharacterGreedy):
(JSC::Yarr::YarrGenerator::backtrackPatternCharacterNonGreedy):
(JSC::Yarr::YarrGenerator::generateCharacterClassOnce):
(JSC::Yarr::YarrGenerator::generateCharacterClassFixed):
(JSC::Yarr::YarrGenerator::generateCharacterClassGreedy):
(JSC::Yarr::YarrGenerator::backtrackCharacterClassNonGreedy):

  • yarr/YarrPattern.cpp:

(JSC::Yarr::YarrPatternConstructor::setupAlternativeOffsets):

  • yarr/YarrPattern.h:

../../../../Volumes/Data/git/WebKit/OpenSource/Source/WebCore:

Add a forwarding header for CheckedArithmetic.h

  • ForwardingHeaders/wtf/CheckedArithmetic.h: Added.

../../../../Volumes/Data/git/WebKit/OpenSource/Tools:

Add test cases for Checked<>

  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/CheckedArithmeticOperations.cpp: Added.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp

    r90962 r94207  
    512512    {
    513513        alternative->m_hasFixedSize = true;
    514         unsigned currentInputPosition = initialInputPosition;
     514        Checked<unsigned> currentInputPosition = initialInputPosition;
    515515
    516516        for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
     
    521521            case PatternTerm::TypeAssertionEOL:
    522522            case PatternTerm::TypeAssertionWordBoundary:
    523                 term.inputPosition = currentInputPosition;
     523                term.inputPosition = currentInputPosition.unsafeGet();
    524524                break;
    525525
    526526            case PatternTerm::TypeBackReference:
    527                 term.inputPosition = currentInputPosition;
     527                term.inputPosition = currentInputPosition.unsafeGet();
    528528                term.frameLocation = currentCallFrameSize;
    529529                currentCallFrameSize += YarrStackSpaceForBackTrackInfoBackReference;
     
    535535
    536536            case PatternTerm::TypePatternCharacter:
    537                 term.inputPosition = currentInputPosition;
     537                term.inputPosition = currentInputPosition.unsafeGet();
    538538                if (term.quantityType != QuantifierFixedCount) {
    539539                    term.frameLocation = currentCallFrameSize;
     
    545545
    546546            case PatternTerm::TypeCharacterClass:
    547                 term.inputPosition = currentInputPosition;
     547                term.inputPosition = currentInputPosition.unsafeGet();
    548548                if (term.quantityType != QuantifierFixedCount) {
    549549                    term.frameLocation = currentCallFrameSize;
     
    560560                    if (term.quantityType != QuantifierFixedCount)
    561561                        currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesOnce;
    562                     currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
     562                    currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition.unsafeGet());
    563563                    // If quantity is fixed, then pre-check its minimum size.
    564564                    if (term.quantityType == QuantifierFixedCount)
    565565                        currentInputPosition += term.parentheses.disjunction->m_minimumSize;
    566                     term.inputPosition = currentInputPosition;
     566                    term.inputPosition = currentInputPosition.unsafeGet();
    567567                } else if (term.parentheses.isTerminal) {
    568568                    currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesTerminal;
    569                     currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
    570                     term.inputPosition = currentInputPosition;
     569                    currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition.unsafeGet());
     570                    term.inputPosition = currentInputPosition.unsafeGet();
    571571                } else {
    572                     term.inputPosition = currentInputPosition;
    573                     setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition);
     572                    term.inputPosition = currentInputPosition.unsafeGet();
     573                    setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition.unsafeGet());
    574574                    currentCallFrameSize += YarrStackSpaceForBackTrackInfoParentheses;
    575575                }
     
    579579
    580580            case PatternTerm::TypeParentheticalAssertion:
    581                 term.inputPosition = currentInputPosition;
     581                term.inputPosition = currentInputPosition.unsafeGet();
    582582                term.frameLocation = currentCallFrameSize;
    583                 currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition);
     583                currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition.unsafeGet());
    584584                break;
    585585
     
    591591        }
    592592
    593         alternative->m_minimumSize = currentInputPosition - initialInputPosition;
     593        alternative->m_minimumSize = (currentInputPosition - initialInputPosition).unsafeGet();
    594594        return currentCallFrameSize;
    595595    }
Note: See TracChangeset for help on using the changeset viewer.