Skip to content

Commit

Permalink
[trace-debug] Global location write fix (#20741)
Browse files Browse the repository at this point in the history
## Description 

This PR fixes trace ingestion for the case when global location is used
in a write to address a problem reported in
#20727

## Test plan 

Added a new test (all new and old tests must pass)
  • Loading branch information
awelc authored Dec 28, 2024
1 parent 4aa53d7 commit 8d0699e
Show file tree
Hide file tree
Showing 28 changed files with 1,805 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/out/
Original file line number Diff line number Diff line change
Expand Up @@ -519,21 +519,25 @@ export function readTrace(
const location = effect.Write ? effect.Write.location : effect.Read!.location;
const loc = processJSONLocalLocation(location, localLifetimeEnds);
if (effect.Write) {
if (!loc) {
throw new Error('Unsupported location type in Write effect');
if (loc !== undefined) {
// Process a write only if the location is supported.
// We can see global location here in some cases when source-level
// assignment does not involve an explicit local variable, along
// the lines of:
//
// field::borrow_mut(...).next = ...
const value = 'RuntimeValue' in effect.Write.root_value_after_write
? traceRuntimeValueFromJSON(effect.Write.root_value_after_write.RuntimeValue.value)
: traceRefValueFromJSON(effect.Write.root_value_after_write);
events.push({
type: TraceEventKind.Effect,
effect: {
type: TraceEffectKind.Write,
loc,
value
}
});
}
// process a write only if the location is supported
const value = 'RuntimeValue' in effect.Write.root_value_after_write
? traceRuntimeValueFromJSON(effect.Write.root_value_after_write.RuntimeValue.value)
: traceRefValueFromJSON(effect.Write.root_value_after_write);
events.push({
type: TraceEventKind.Effect,
effect: {
type: TraceEffectKind.Write,
loc,
value
}
});
}
}
if (effect.ExecutionError) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "global_write"
edition = "2024.beta"

[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/mainnet" }

[addresses]
global_write = "0x0"
Sui = "0x2"
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"definition_location":{"file_hash":[54,47,138,104,171,115,23,224,131,176,160,65,21,99,189,119,64,168,202,80,38,98,202,231,44,226,206,16,224,130,113,119],"start":155,"end":161},"module_name":["0000000000000000000000000000000000000000000000000000000000000001","macros"],"struct_map":{},"enum_map":{},"function_map":{"0":{"location":{"file_hash":[54,47,138,104,171,115,23,224,131,176,160,65,21,99,189,119,64,168,202,80,38,98,202,231,44,226,206,16,224,130,113,119],"start":143,"end":6955},"definition_location":{"file_hash":[54,47,138,104,171,115,23,224,131,176,160,65,21,99,189,119,64,168,202,80,38,98,202,231,44,226,206,16,224,130,113,119],"start":143,"end":6955},"type_parameters":[],"parameters":[],"returns":[],"locals":[],"nops":{},"code_map":{"0":{"file_hash":[54,47,138,104,171,115,23,224,131,176,160,65,21,99,189,119,64,168,202,80,38,98,202,231,44,226,206,16,224,130,113,119],"start":143,"end":6955}},"is_native":false}},"constant_map":{}}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"definition_location":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":86,"end":87},"module_name":["0000000000000000000000000000000000000000000000000000000000000000","m"],"struct_map":{},"enum_map":{},"function_map":{"0":{"location":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":122,"end":665},"definition_location":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":126,"end":130},"type_parameters":[],"parameters":[],"returns":[],"locals":[["%#1",{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":154,"end":173}],["table#1#0",{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":187,"end":192}]],"nops":{},"code_map":{"0":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":154,"end":173},"2":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":149,"end":173},"3":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":195,"end":226},"4":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":183,"end":192},"5":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":232,"end":237},"6":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":248,"end":249},"7":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":251,"end":253},"8":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":232,"end":254},"9":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":622,"end":627},"10":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":638,"end":640},"11":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":642,"end":643},"12":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":622,"end":644},"13":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":650,"end":655},"14":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":650,"end":662},"15":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":662,"end":663}},"is_native":false},"1":{"location":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":65,"end":665},"definition_location":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":65,"end":665},"type_parameters":[],"parameters":[],"returns":[],"locals":[],"nops":{},"code_map":{"0":{"file_hash":[236,192,52,171,254,22,100,62,124,245,221,113,238,213,97,152,169,36,102,67,48,142,226,112,206,244,8,26,40,241,165,204],"start":65,"end":665}},"is_native":false}},"constant_map":{}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

/// This module holds shared implementation of macros used in `std`
module std::macros;

use std::string::String;

public macro fun num_max($x: _, $y: _): _ {
let x = $x;
let y = $y;
if (x > y) x
else y
}

public macro fun num_min($x: _, $y: _): _ {
let x = $x;
let y = $y;
if (x < y) x
else y
}

public macro fun num_diff($x: _, $y: _): _ {
let x = $x;
let y = $y;
if (x > y) x - y
else y - x
}

public macro fun num_divide_and_round_up($x: _, $y: _): _ {
let x = $x;
let y = $y;
if (x % y == 0) x / y
else x / y + 1
}

public macro fun num_pow($base: _, $exponent: u8): _ {
let mut base = $base;
let mut exponent = $exponent;
let mut res = 1;
while (exponent >= 1) {
if (exponent % 2 == 0) {
base = base * base;
exponent = exponent / 2;
} else {
res = res * base;
exponent = exponent - 1;
}
};

res
}

public macro fun num_sqrt<$T, $U>($x: $T, $bitsize: u8): $T {
let x = $x;
let mut bit = (1: $U) << $bitsize;
let mut res = (0: $U);
let mut x = x as $U;

while (bit != 0) {
if (x >= res + bit) {
x = x - (res + bit);
res = (res >> 1) + bit;
} else {
res = res >> 1;
};
bit = bit >> 2;
};

res as $T
}

public macro fun num_to_string($x: _): String {
let mut x = $x;
if (x == 0) {
return b"0".to_string()
};
let mut buffer = vector[];
while (x != 0) {
buffer.push_back(((48 + x % 10) as u8));
x = x / 10;
};
buffer.reverse();
buffer.to_string()
}

public macro fun range_do($start: _, $stop: _, $f: |_|) {
let mut i = $start;
let stop = $stop;
while (i < stop) {
$f(i);
i = i + 1;
}
}

public macro fun range_do_eq($start: _, $stop: _, $f: |_|) {
let mut i = $start;
let stop = $stop;
// we check `i >= stop` inside the loop instead of `i <= stop` as `while` condition to avoid
// incrementing `i` past the MAX integer value.
// Because of this, we need to check if `i > stop` and return early--instead of letting the
// loop bound handle it, like in the `range_do` macro.
if (i > stop) return;
loop {
$f(i);
if (i >= stop) break;
i = i + 1;
}
}

public macro fun do($stop: _, $f: |_|) {
range_do!(0, $stop, $f)
}

public macro fun do_eq($stop: _, $f: |_|) {
range_do_eq!(0, $stop, $f)
}

public macro fun try_as_u8($x: _): Option<u8> {
let x = $x;
if (x > 0xFF) option::none()
else option::some(x as u8)
}

public macro fun try_as_u16($x: _): Option<u16> {
let x = $x;
if (x > 0xFFFF) option::none()
else option::some(x as u16)
}

public macro fun try_as_u32($x: _): Option<u32> {
let x = $x;
if (x > 0xFFFF_FFFF) option::none()
else option::some(x as u32)
}

public macro fun try_as_u64($x: _): Option<u64> {
let x = $x;
if (x > 0xFFFF_FFFF_FFFF_FFFF) option::none()
else option::some(x as u64)
}

public macro fun try_as_u128($x: _): Option<u128> {
let x = $x;
if (x > 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF) option::none()
else option::some(x as u128)
}

/// Creates a fixed-point value from a quotient specified by its numerator and denominator.
/// `$T` is the underlying integer type for the fixed-point value, where `$T` has `$t_bits` bits.
/// `$U` is the type used for intermediate calculations, where `$U` is the next larger integer type.
/// `$max_t` is the maximum value that can be represented by `$T`.
/// `$t_bits` (as mentioned above) is the total number of bits in the fixed-point value (integer
/// plus fractional).
/// `$fractional_bits` is the number of fractional bits in the fixed-point value.
public macro fun uq_from_quotient<$T, $U>(
$numerator: $T,
$denominator: $T,
$max_t: $T,
$t_bits: u8,
$fractional_bits: u8,
$abort_denominator: _,
$abort_quotient_too_small: _,
$abort_quotient_too_large: _,
): $T {
let numerator = $numerator;
let denominator = $denominator;
if (denominator == 0) $abort_denominator;

// Scale the numerator to have `$t_bits` fractional bits and the denominator to have
// `$t_bits - $fractional_bits` fractional bits, so that the quotient will have
// `$fractional_bits` fractional bits.
let scaled_numerator = numerator as $U << $t_bits;
let scaled_denominator = denominator as $U << ($t_bits - $fractional_bits);
let quotient = scaled_numerator / scaled_denominator;

// The quotient can only be zero if the numerator is also zero.
if (quotient == 0 && numerator != 0) $abort_quotient_too_small;

// Return the quotient as a fixed-point number. We first need to check whether the cast
// can succeed.
if (quotient > $max_t as $U) $abort_quotient_too_large;
quotient as $T
}

public macro fun uq_from_int<$T, $U>($integer: $T, $fractional_bits: u8): $U {
($integer as $U) << $fractional_bits
}

public macro fun uq_add<$T, $U>($a: $T, $b: $T, $max_t: $T, $abort_overflow: _): $T {
let sum = $a as $U + ($b as $U);
if (sum > $max_t as $U) $abort_overflow;
sum as $T
}

public macro fun uq_sub<$T>($a: $T, $b: $T, $abort_overflow: _): $T {
let a = $a;
let b = $b;
if (a < b) $abort_overflow;
a - b
}

public macro fun uq_to_int<$T, $U>($a: $U, $fractional_bits: u8): $T {
($a >> $fractional_bits) as $T
}

public macro fun uq_int_mul<$T, $U>(
$val: $T,
$multiplier: $T,
$max_t: $T,
$fractional_bits: u8,
$abort_overflow: _,
): $T {
// The product of two `$T` bit values has the same number of bits as `$U`, so perform the
// multiplication with `$U` types and keep the full `$U` bit product
// to avoid losing accuracy.
let unscaled_product = $val as $U * ($multiplier as $U);
// The unscaled product has `$fractional_bits` fractional bits (from the multiplier)
// so rescale it by shifting away the low bits.
let product = unscaled_product >> $fractional_bits;
// Check whether the value is too large.
if (product > $max_t as $U) $abort_overflow;
product as $T
}

public macro fun uq_int_div<$T, $U>(
$val: $T,
$divisor: $T,
$max_t: $T,
$fractional_bits: u8,
$abort_division_by_zero: _,
$abort_overflow: _,
): $T {
let val = $val;
let divisor = $divisor;
// Check for division by zero.
if (divisor == 0) $abort_division_by_zero;
// First convert to $U to increase the number of bits to the next integer size
// and then shift left to add `$fractional_bits` fractional zero bits to the dividend.
let scaled_value = val as $U << $fractional_bits;
let quotient = scaled_value / (divisor as $U);
// Check whether the value is too large.
if (quotient > $max_t as $U) $abort_overflow;
quotient as $T
}
Loading

0 comments on commit 8d0699e

Please sign in to comment.