-
Notifications
You must be signed in to change notification settings - Fork 50
Enable quantification optimizations for scalar semantics #671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 5 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
bade9d2
[testing] Quantified scalar semantic matching
milseman f0f4c03
encode is scalar semantics in quantify instruction
milseman 9bc82a5
wip: turn on optimizations, but there's one test that fails
milseman ed1a5c2
Track scalar semantics for quantifier save points
milseman 77c7dae
Add some more scalar quantification tests
milseman db9120c
Cleanup and more tests
milseman 24ad4bc
cleanup tests
milseman File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,11 @@ extension Processor { | |
// Quantifiers may store a range of positions to restore to | ||
var rangeStart: Position? | ||
var rangeEnd: Position? | ||
|
||
// FIXME: refactor, for now this field is only used for quantifier save | ||
// points. We should try to separate out the concerns better. | ||
var isScalarSemantics: Bool | ||
|
||
// The end of the call stack, so we can slice it off | ||
// when failing inside a call. | ||
// | ||
|
@@ -68,7 +73,11 @@ extension Processor { | |
rangeStart = nil | ||
rangeEnd = nil | ||
} else { | ||
input.formIndex(before: &rangeEnd!) | ||
if isScalarSemantics { | ||
input.unicodeScalars.formIndex(before: &rangeEnd!) | ||
} else { | ||
input.formIndex(before: &rangeEnd!) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice 👍🏻 |
||
} | ||
} | ||
} | ||
|
@@ -82,19 +91,23 @@ extension Processor { | |
pos: addressOnly ? nil : currentPosition, | ||
rangeStart: nil, | ||
rangeEnd: nil, | ||
isScalarSemantics: false, // FIXME: refactor away | ||
stackEnd: .init(callStack.count), | ||
captureEnds: storedCaptures, | ||
intRegisters: registers.ints, | ||
posRegisters: registers.positions) | ||
} | ||
|
||
func startQuantifierSavePoint() -> SavePoint { | ||
func startQuantifierSavePoint( | ||
isScalarSemantics: Bool | ||
) -> SavePoint { | ||
// Restores to the instruction AFTER the current quantifier instruction | ||
SavePoint( | ||
pc: controller.pc + 1, | ||
pos: nil, | ||
rangeStart: nil, | ||
rangeEnd: nil, | ||
isScalarSemantics: isScalarSemantics, | ||
stackEnd: .init(callStack.count), | ||
captureEnds: storedCaptures, | ||
intRegisters: registers.ints, | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -370,6 +370,10 @@ extension Instruction.Payload { | |||
} | ||||
} | ||||
|
||||
// TODO: Consider switching all quantification to a quantification | ||||
// instruction, where the general path has an instruction list (i.e. a | ||||
// slice of a list) | ||||
|
||||
// MARK: Struct definitions | ||||
struct QuantifyPayload: RawRepresentable { | ||||
let rawValue: UInt64 | ||||
|
@@ -380,9 +384,12 @@ struct QuantifyPayload: RawRepresentable { | |||
case builtin = 4 | ||||
} | ||||
|
||||
// TODO: figure out how to better organize this... | ||||
|
||||
// Future work: optimize this layout -> payload type should be a fast switch | ||||
// The top 8 bits are reserved for the opcode so we have 56 bits to work with | ||||
// b55-b38 - Unused | ||||
// b55-b39 - Unused | ||||
// b39-b38 - isScalarSemantics | ||||
// b38-b35 - Payload type (one of 4 types, stored on 3 bits) | ||||
// b35-b27 - minTrips (8 bit int) | ||||
// b27-b18 - extraTrips (8 bit value, one bit for nil) | ||||
|
@@ -393,6 +400,7 @@ struct QuantifyPayload: RawRepresentable { | |||
static var minTripsShift: UInt64 { 27 } | ||||
static var typeShift: UInt64 { 35 } | ||||
static var maxStorableTrips: UInt64 { (1 << 8) - 1 } | ||||
static var isScalarSemanticsBit: UInt64 { 1 &<< 38 } | ||||
|
||||
var quantKindMask: UInt64 { 3 } | ||||
var extraTripsMask: UInt64 { 0x1FF } | ||||
|
@@ -404,7 +412,8 @@ struct QuantifyPayload: RawRepresentable { | |||
_ kind: AST.Quantification.Kind, | ||||
_ minTrips: Int, | ||||
_ extraTrips: Int?, | ||||
_ type: PayloadType | ||||
_ type: PayloadType, | ||||
isScalarSemantics: Bool | ||||
) -> UInt64 { | ||||
let kindVal: UInt64 | ||||
switch kind { | ||||
|
@@ -415,11 +424,14 @@ struct QuantifyPayload: RawRepresentable { | |||
case .possessive: | ||||
kindVal = 2 | ||||
} | ||||
// TODO: refactor / reimplement | ||||
let extraTripsVal: UInt64 = extraTrips == nil ? 1 : UInt64(extraTrips!) << 1 | ||||
return (kindVal << QuantifyPayload.quantKindShift) + | ||||
(extraTripsVal << QuantifyPayload.extraTripsShift) + | ||||
(UInt64(minTrips) << QuantifyPayload.minTripsShift) + | ||||
(type.rawValue << QuantifyPayload.typeShift) | ||||
let scalarSemanticsBit = isScalarSemantics ? Self.isScalarSemanticsBit : 0 | ||||
return (kindVal << QuantifyPayload.quantKindShift) | | ||||
(extraTripsVal << QuantifyPayload.extraTripsShift) | | ||||
(UInt64(minTrips) << QuantifyPayload.minTripsShift) | | ||||
(type.rawValue << QuantifyPayload.typeShift) | | ||||
scalarSemanticsBit | ||||
} | ||||
|
||||
init(rawValue: UInt64) { | ||||
|
@@ -431,46 +443,50 @@ struct QuantifyPayload: RawRepresentable { | |||
bitset: AsciiBitsetRegister, | ||||
_ kind: AST.Quantification.Kind, | ||||
_ minTrips: Int, | ||||
_ extraTrips: Int? | ||||
_ extraTrips: Int?, | ||||
isScalarSemantics: Bool | ||||
) { | ||||
assert(bitset.bits <= _payloadMask) | ||||
self.rawValue = bitset.bits | ||||
+ QuantifyPayload.packInfoValues(kind, minTrips, extraTrips, .bitset) | ||||
+ QuantifyPayload.packInfoValues(kind, minTrips, extraTrips, .bitset, isScalarSemantics: isScalarSemantics) | ||||
} | ||||
|
||||
init( | ||||
asciiChar: UInt8, | ||||
_ kind: AST.Quantification.Kind, | ||||
_ minTrips: Int, | ||||
_ extraTrips: Int? | ||||
_ extraTrips: Int?, | ||||
isScalarSemantics: Bool | ||||
) { | ||||
self.rawValue = UInt64(asciiChar) | ||||
+ QuantifyPayload.packInfoValues(kind, minTrips, extraTrips, .asciiChar) | ||||
+ QuantifyPayload.packInfoValues(kind, minTrips, extraTrips, .asciiChar, isScalarSemantics: isScalarSemantics) | ||||
} | ||||
|
||||
init( | ||||
matchesNewlines: Bool, | ||||
_ kind: AST.Quantification.Kind, | ||||
_ minTrips: Int, | ||||
_ extraTrips: Int? | ||||
_ extraTrips: Int?, | ||||
isScalarSemantics: Bool | ||||
) { | ||||
self.rawValue = (matchesNewlines ? 1 : 0) | ||||
+ QuantifyPayload.packInfoValues(kind, minTrips, extraTrips, .any) | ||||
+ QuantifyPayload.packInfoValues(kind, minTrips, extraTrips, .any, isScalarSemantics: isScalarSemantics) | ||||
} | ||||
|
||||
init( | ||||
model: _CharacterClassModel, | ||||
_ kind: AST.Quantification.Kind, | ||||
_ minTrips: Int, | ||||
_ extraTrips: Int? | ||||
_ extraTrips: Int?, | ||||
isScalarSemantics: Bool | ||||
) { | ||||
assert(model.cc.rawValue < 0xFF) | ||||
assert(model.matchLevel != .unicodeScalar) | ||||
// assert(model.matchLevel != .unicodeScalar) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
let packedModel = model.cc.rawValue | ||||
+ (model.isInverted ? 1 << 9 : 0) | ||||
+ (model.isStrictASCII ? 1 << 10 : 0) | ||||
self.rawValue = packedModel | ||||
+ QuantifyPayload.packInfoValues(kind, minTrips, extraTrips, .builtin) | ||||
+ QuantifyPayload.packInfoValues(kind, minTrips, extraTrips, .builtin, isScalarSemantics: isScalarSemantics) | ||||
} | ||||
|
||||
var type: PayloadType { | ||||
|
@@ -500,6 +516,10 @@ struct QuantifyPayload: RawRepresentable { | |||
} | ||||
} | ||||
|
||||
var isScalarSemantics: Bool { | ||||
rawValue & Self.isScalarSemanticsBit != 0 | ||||
} | ||||
|
||||
var bitset: AsciiBitsetRegister { | ||||
TypedInt(self.rawValue & payloadMask) | ||||
} | ||||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leftover?