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/YarrJIT.cpp

    r90962 r94207  
    561561                matchDest.append(atEndOfInput());
    562562
    563             readCharacter((term->inputPosition - m_checked), character);
     563            readCharacter(term->inputPosition - m_checked, character);
    564564            matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass());
    565565            op.m_jumps.append(jump());
     
    717717
    718718        move(index, countRegister);
    719         sub32(Imm32(term->quantityCount), countRegister);
     719        sub32(Imm32(term->quantityCount.unsafeGet()), countRegister);
    720720
    721721        Label loop(this);
    722         BaseIndex address(input, countRegister, TimesTwo, (term->inputPosition - m_checked + term->quantityCount) * sizeof(UChar));
     722        BaseIndex address(input, countRegister, TimesTwo, ((term->inputPosition - m_checked + Checked<int>(term->quantityCount)) * static_cast<int>(sizeof(UChar))).unsafeGet());
    723723
    724724        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
     
    766766            jump(loop);
    767767        else
    768             branch32(NotEqual, countRegister, Imm32(term->quantityCount)).linkTo(loop, this);
     768            branch32(NotEqual, countRegister, Imm32(term->quantityCount.unsafeGet())).linkTo(loop, this);
    769769
    770770        failures.link(this);
     
    818818        nonGreedyFailures.append(atEndOfInput());
    819819        if (term->quantityCount != quantifyInfinite)
    820             nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount)));
     820            nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount.unsafeGet())));
    821821        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
    822822            readCharacter(term->inputPosition - m_checked, character);
     
    846846
    847847        JumpList matchDest;
    848         readCharacter((term->inputPosition - m_checked), character);
     848        readCharacter(term->inputPosition - m_checked, character);
    849849        matchCharacterClass(character, matchDest, term->characterClass);
    850850
     
    870870
    871871        move(index, countRegister);
    872         sub32(Imm32(term->quantityCount), countRegister);
     872        sub32(Imm32(term->quantityCount.unsafeGet()), countRegister);
    873873
    874874        Label loop(this);
    875875        JumpList matchDest;
    876         load16(BaseIndex(input, countRegister, TimesTwo, (term->inputPosition - m_checked + term->quantityCount) * sizeof(UChar)), character);
     876        load16(BaseIndex(input, countRegister, TimesTwo, ((term->inputPosition - m_checked + Checked<int>(term->quantityCount)) * static_cast<int>(sizeof(UChar))).unsafeGet()), character);
    877877        matchCharacterClass(character, matchDest, term->characterClass);
    878878
     
    920920        add32(TrustedImm32(1), index);
    921921        if (term->quantityCount != quantifyInfinite) {
    922             branch32(NotEqual, countRegister, Imm32(term->quantityCount)).linkTo(loop, this);
     922            branch32(NotEqual, countRegister, Imm32(term->quantityCount.unsafeGet())).linkTo(loop, this);
    923923            failures.append(jump());
    924924        } else
     
    973973
    974974        nonGreedyFailures.append(atEndOfInput());
    975         nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount)));
     975        nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount.unsafeGet())));
    976976
    977977        JumpList matchDest;
Note: See TracChangeset for help on using the changeset viewer.