Skip to content
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

Adds OpcodeKind, LengthType to Opcode #836

Merged
merged 2 commits into from
Sep 18, 2024
Merged

Adds OpcodeKind, LengthType to Opcode #836

merged 2 commits into from
Sep 18, 2024

Conversation

zslayton
Copy link
Contributor

@zslayton zslayton commented Sep 18, 2024

This PR aims to merge some optimizations that were implemented in a demo branch a while back. In particular, it:

  • moves the logic needed to determine the LengthType for a given Opcode from runtime to compile time, streamlining the process of reading a value/e-expression.
  • adds an OpcodeKind to the Opcode struct, allowing the reader to check for high-level categories of syntactic elements like "value", "e-expression", or "annotations" rather than matching against all possible OpcodeTypes in each category.
  • Batches up parsed e-expression arguments and copies them to the bump allocator in bulk.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Copy link
Contributor Author

@zslayton zslayton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺️ PR tour 🧭

Comment on lines -449 to +446
// TODO: Make an `OpcodeClass` enum that captures groups like this for fewer branches
if opcode.is_e_expression() || opcode.ion_type.is_some() || opcode.is_annotations_sequence()
if opcode.is_e_expression()
|| opcode.ion_type().is_some()
|| opcode.is_annotations_sequence()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺️ This code snippet is just a whitespace change. The deleted comment has now been implemented; opcode.is_e_expression() now involves matching against a single value instead of 4+.

Comment on lines -33 to +41
static ION_1_1_TIMESTAMP_SHORT_SIZE: [u8; 13] = [1, 2, 2, 4, 5, 6, 7, 8, 5, 5, 7, 8, 9];
const ION_1_1_TIMESTAMP_SHORT_SIZE: [u8; 13] = [1, 2, 2, 4, 5, 6, 7, 8, 5, 5, 7, 8, 9];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺️ static elements cannot be referenced in a const fn, but const elements can. This is effectively making a copy of this array each time it is referenced. Because it's only 13 bytes and is used once, it's not expensive.

Comment on lines -184 to +273
use LengthType::*;
match (self.ion_type_code, self.low_nibble) {
(OpcodeType::Boolean, 0xE..=0xF) => InOpcode(0),
(OpcodeType::Float, 0xA) => InOpcode(0),
(OpcodeType::Float, 0xB..=0xD) => InOpcode(1 << (self.low_nibble - 0xA)),
(OpcodeType::Integer, n) => InOpcode(n),
(OpcodeType::Nop, 0xC) => InOpcode(0),
(OpcodeType::NullNull, 0xA) => InOpcode(0),
(OpcodeType::String, 0..=15) => InOpcode(self.low_nibble),
(OpcodeType::InlineSymbol, n) if n < 16 => InOpcode(n),
(OpcodeType::SymbolAddress, n) if n < 4 => InOpcode(n),
(OpcodeType::Decimal, 0..=15) => InOpcode(self.low_nibble),
(OpcodeType::List, n) if n < 16 => InOpcode(n),
(OpcodeType::SExpression, n) if n < 16 => InOpcode(n),
(OpcodeType::TimestampShort, 0..=12) => {
InOpcode(ION_1_1_TIMESTAMP_SHORT_SIZE[self.low_nibble as usize])
}
(OpcodeType::TypedNull, _) => InOpcode(1),
(OpcodeType::Struct, n) if n < 16 => InOpcode(n),
(OpcodeType::DelimitedContainerClose, 0) => InOpcode(0),
(
OpcodeType::ListDelimited
| OpcodeType::SExpressionDelimited
| OpcodeType::StructDelimited,
_,
) => Unknown,
_ => FlexUIntFollows,
}
self.length_type
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺️ This code block would often cause BinaryBuffer::read_value_length to not be inlined. Now this logic happens at compile time instead.

Comment on lines -399 to +400
EExpressionWith6BitAddress
| EExpressionWith12BitAddress
| EExpressionWith20BitAddress
| EExpressionWithLengthPrefix => {
ParseValueExprResult::EExp(self.read_e_expression(opcode))
}
AnnotationFlexSym | AnnotationSymAddress => {
let result = match opcode.kind {
OpcodeKind::EExp => ParseValueExprResult::EExp(self.read_e_expression(opcode)),
OpcodeKind::Annotations => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺️ Notice that all of these match arms have been consolidated because we now check the kind instead of the opcode_type.

@zslayton zslayton marked this pull request as ready for review September 18, 2024 10:02
@zslayton zslayton requested review from popematt and nirosys and removed request for popematt September 18, 2024 10:02
@@ -55,56 +63,131 @@ impl Opcode {
/// opcode + length code combination is illegal, an error will be returned.
pub const fn from_byte(byte: u8) -> Opcode {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗺️ This method is run at compile time to compute a u8->Opcode cache. I've augmented it to also compute the LengthType and OpcodeKind for each byte.

Copy link
Contributor

@popematt popematt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall. I have just a few minor suggestions.

src/lazy/binary/raw/v1_1/type_descriptor.rs Outdated Show resolved Hide resolved
src/lazy/binary/raw/v1_1/type_descriptor.rs Outdated Show resolved Hide resolved
src/lazy/binary/raw/v1_1/type_descriptor.rs Outdated Show resolved Hide resolved
src/lazy/binary/raw/v1_1/type_descriptor.rs Outdated Show resolved Hide resolved
@zslayton zslayton merged commit c17b5c8 into main Sep 18, 2024
33 checks passed
@zslayton zslayton deleted the opcode-kind branch September 18, 2024 17:14
@zslayton zslayton restored the opcode-kind branch September 18, 2024 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants