Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sources/ComputeCxx/Comparison/Builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Builder : public swift::metadata_visitor {
const swift::existential_type_metadata *type;
};
struct HeapRefItem : RangeItem {
bool is_function;
bool is_capture_ref;
};
struct NestedItem : RangeItem {
ValueLayout layout;
Expand Down
35 changes: 27 additions & 8 deletions Sources/ComputeCxx/Comparison/Compare.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "Compare.h"

#include <cstring>

#include "Graph/Graph.h"
#include "Swift/Metadata.h"
#include "Swift/SwiftShims.h"
Expand Down Expand Up @@ -127,13 +129,24 @@ bool Compare::operator()(ValueLayout layout, const unsigned char *lhs, const uns
}
case ValueLayoutEntryKind::Indirect: {
auto type = reader.read_bytes<const swift::metadata *>();
auto indirect_layout = reader.read_bytes<ValueLayout>();

unsigned char *indirect_layout_ptr = const_cast<unsigned char *>(reader.layout);
ValueLayout indirect_layout;
std::memcpy(&indirect_layout, indirect_layout_ptr, sizeof(indirect_layout));
reader.skip(sizeof(indirect_layout));

size_t item_size = type->vw_size();
size_t item_end = offset + item_size;

if (!compare_indirect(&indirect_layout, *_enums.back().type, *type,
options & ~IAGComparisonOptionsTraceCompareFailed, lhs + offset, rhs + offset)) {
bool equal =
compare_indirect(&indirect_layout, *_enums.back().type, *type,
options & ~IAGComparisonOptionsTraceCompareFailed, lhs + offset, rhs + offset);

// Persist the (possibly newly-fetched) indirect layout
// Layout fetch is idempotent for a given type and options
std::memcpy(indirect_layout_ptr, &indirect_layout, sizeof(indirect_layout));

if (!equal) {
failed(options, lhs, rhs, offset, item_size, type);
return false;
}
Expand All @@ -158,14 +171,20 @@ bool Compare::operator()(ValueLayout layout, const unsigned char *lhs, const uns
continue;
}
case ValueLayoutEntryKind::HeapRef:
case ValueLayoutEntryKind::Function: {
bool is_function = kind == ValueLayoutEntryKind::Function;
case ValueLayoutEntryKind::CaptureRef: {
bool is_capture_ref = kind == ValueLayoutEntryKind::CaptureRef;

size_t item_end = offset + 8;

if (lhs + offset != rhs + offset) {
if (!compare_heap_objects(lhs + offset, rhs + offset, options & ~IAGComparisonOptionsTraceCompareFailed,
is_function)) {
// The buffer at offset stores a pointer to the heap object.
const void *lhs_object;
const void *rhs_object;
std::memcpy(&lhs_object, lhs + offset, sizeof(lhs_object));
std::memcpy(&rhs_object, rhs + offset, sizeof(rhs_object));

if (lhs_object != rhs_object) {
auto heap_object_options = options & ~IAGComparisonOptionsTraceCompareFailed;
if (!compare_heap_objects(lhs_object, rhs_object, heap_object_options, is_capture_ref)) {
failed(options, lhs, rhs, offset, 8, nullptr);
return false;
}
Expand Down
39 changes: 23 additions & 16 deletions Sources/ComputeCxx/Comparison/LayoutDescriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ size_t length(ValueLayout layout) {
reader.skip(sizeof(void *));
continue;
case ValueLayoutEntryKind::HeapRef:
case ValueLayoutEntryKind::Function:
case ValueLayoutEntryKind::CaptureRef:
continue;
case ValueLayoutEntryKind::Nested:
reader.skip(sizeof(void *));
Expand Down Expand Up @@ -452,7 +452,11 @@ bool compare_bytes(const unsigned char *lhs, const unsigned char *rhs, size_t si
// If both aligned to 8 bytes, compare 8 bytes at a time
if ((((uintptr_t)lhs | (uintptr_t)rhs) & 7) == 0) {
while (remaining_size >= 8) {
if (*(uint64_t *)lhs != *(uint64_t *)rhs) {
uint64_t lhs_word;
uint64_t rhs_word;
std::memcpy(&lhs_word, lhs, sizeof(lhs_word));
std::memcpy(&rhs_word, rhs, sizeof(rhs_word));
if (lhs_word != rhs_word) {
if (failure_location) {
*failure_location = location;
}
Expand All @@ -467,7 +471,7 @@ bool compare_bytes(const unsigned char *lhs, const unsigned char *rhs, size_t si

// Compare one byte at a time
while (remaining_size > 0) {
if (*(uint8_t *)lhs != *(uint8_t *)rhs) {
if (*lhs != *rhs) {
if (failure_location) {
*failure_location = location;
}
Expand All @@ -482,28 +486,31 @@ bool compare_bytes(const unsigned char *lhs, const unsigned char *rhs, size_t si
return true;
}

bool compare_heap_objects(const unsigned char *lhs, const unsigned char *rhs, IAGComparisonOptions options,
bool is_function) {
bool compare_heap_objects(const void *lhs, const void *rhs, IAGComparisonOptions options, bool is_capture_ref) {
if (lhs == rhs) {
return true;
}
if (lhs == nullptr || rhs == nullptr) {
return false;
}

auto lhs_type = (const swift::metadata *)lhs;
auto rhs_type = (const swift::metadata *)rhs;
// The first field of a Swift HeapObject is a pointer to its metadata.
const swift::metadata *lhs_type;
const swift::metadata *rhs_type;
std::memcpy(&lhs_type, lhs, sizeof(lhs_type));
std::memcpy(&rhs_type, rhs, sizeof(rhs_type));
if (lhs_type != rhs_type) {
return false;
}

HeapMode heap_mode = is_function ? HeapMode::Locals : HeapMode::Class;
IAGComparisonOptions fetch_options = options & IAGComparisonOptionsComparisonModeMask; // this has the effect of
// allowing async fetch
HeapMode heap_mode = is_capture_ref ? HeapMode::Locals : HeapMode::Class;
// this has the effect of allowing async fetch
IAGComparisonOptions fetch_options = options & IAGComparisonOptionsComparisonModeMask;
ValueLayout layout = TypeDescriptorCache::shared_cache().fetch(*lhs_type, fetch_options, heap_mode, 1);

if (layout > ValueLayoutTrivial) {
return compare(layout, lhs, rhs, -1, options & ~IAGComparisonOptionsCopyOnWrite);
return compare(layout, (const unsigned char *)lhs, (const unsigned char *)rhs, -1,
options & ~IAGComparisonOptionsCopyOnWrite);
}

return false;
Expand Down Expand Up @@ -549,7 +556,7 @@ bool compare_indirect(ValueLayout *layout_ref, const swift::metadata &enum_type,

// compare as heap objects
bool result;
if (*lhs_copy == *rhs_copy) {
if (std::memcmp(lhs_copy, rhs_copy, sizeof(void *)) == 0) {
// projected data are referentially equal
result = true;
} else {
Expand Down Expand Up @@ -681,7 +688,7 @@ Partial find_partial(ValueLayout layout, size_t range_location, size_t range_siz
continue;
}
case ValueLayoutEntryKind::HeapRef:
case ValueLayoutEntryKind::Function: {
case ValueLayoutEntryKind::CaptureRef: {
accumulated_size += sizeof(void *);
continue;
}
Expand Down Expand Up @@ -840,7 +847,7 @@ void print(std::string &output, ValueLayout layout) {
continue;
}
case ValueLayoutEntryKind::HeapRef:
case ValueLayoutEntryKind::Function: {
case ValueLayoutEntryKind::CaptureRef: {
bool is_heap_ref = kind == ValueLayoutEntryKind::HeapRef;

output.push_back('\n');
Expand Down Expand Up @@ -1287,8 +1294,8 @@ void Builder::Emitter<vector<unsigned char, 512, uint64_t>>::operator()(const Ex

void Builder::Emitter<vector<unsigned char, 512, uint64_t>>::operator()(const HeapRefItem &item) {
enter(item);
_data->push_back(item.is_function ? (unsigned char)ValueLayoutEntryKind::Function
: (unsigned char)ValueLayoutEntryKind::HeapRef);
_data->push_back(item.is_capture_ref ? (unsigned char)ValueLayoutEntryKind::CaptureRef
: (unsigned char)ValueLayoutEntryKind::HeapRef);
_emitted_size += item.size;
}

Expand Down
3 changes: 1 addition & 2 deletions Sources/ComputeCxx/Comparison/LayoutDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ bool compare(ValueLayout layout, const unsigned char *lhs, const unsigned char *
bool compare_bytes_top_level(const unsigned char *lhs, const unsigned char *rhs, size_t size,
IAGComparisonOptions options);
bool compare_bytes(char unsigned const *lhs, char unsigned const *rhs, size_t size, size_t *_Nullable failure_location);
bool compare_heap_objects(char unsigned const *lhs, char unsigned const *rhs, IAGComparisonOptions options,
bool is_function);
bool compare_heap_objects(const void *lhs, const void *rhs, IAGComparisonOptions options, bool is_capture_ref);
bool compare_indirect(ValueLayout _Nullable *_Nullable layout_ref, const swift::metadata &lhs_type,
const swift::metadata &rhs_type, IAGComparisonOptions options, const unsigned char *lhs,
const unsigned char *rhs);
Expand Down
2 changes: 1 addition & 1 deletion Sources/ComputeCxx/Comparison/ValueLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ enum class ValueLayoutEntryKind : uint8_t {
Indirect = '\x02',
Existential = '\x03',
HeapRef = '\x04',
Function = '\x05',
CaptureRef = '\x05',
Nested = '\x06',
CompactNested = '\x07',

Expand Down
2 changes: 1 addition & 1 deletion Xcode/Configs/Compute.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ USE_HEADERMAP = NO
CODE_SIGN_STYLE = Automatic

CURRENT_PROJECT_VERSION = 1
MARKETING_VERSION = 0.5.0
MARKETING_VERSION = 0.5.1

ENABLE_MODULE_VERIFIER = YES
MODULE_VERIFIER_SUPPORTED_LANGUAGES = objective-c objective-c++
Expand Down