mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
![Ryan Macnak](/assets/img/avatar_default.png)
Change-Id: Ia3127ba9ef4ee1faf1f85a6eaa0dafd0cf187b2b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99376 Reviewed-by: Aart Bik <ajcbik@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Samir Jindel <sjindel@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
200 lines
4.8 KiB
C++
200 lines
4.8 KiB
C++
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "platform/assert.h"
|
|
#include "vm/code_descriptors.h"
|
|
#include "vm/exceptions.h"
|
|
#include "vm/unit_test.h"
|
|
|
|
namespace dart {
|
|
|
|
static CatchEntryMove NewMove(intptr_t src, intptr_t dst) {
|
|
return CatchEntryMove::FromSlot(CatchEntryMove::SourceKind::kTaggedSlot, src,
|
|
dst);
|
|
}
|
|
const auto kA = NewMove(1, 10);
|
|
const auto kB = NewMove(2, 20);
|
|
const auto kC = NewMove(3, 30);
|
|
const auto kD = NewMove(4, 40);
|
|
const auto kE = NewMove(5, 50);
|
|
const auto kX = NewMove(-1, -10);
|
|
|
|
const CatchEntryMove abcde[] = {kA, kB, kC, kD, kE};
|
|
const CatchEntryMove abcdx[] = {kA, kB, kC, kD, kX};
|
|
const CatchEntryMove xbcde[] = {kX, kB, kC, kD, kE};
|
|
const CatchEntryMove abxde[] = {kA, kB, kX, kD, kE};
|
|
const CatchEntryMove ab[] = {kA, kB};
|
|
const CatchEntryMove de[] = {kD, kE};
|
|
|
|
struct TestCaseMoves {
|
|
const CatchEntryMove* moves;
|
|
const intptr_t count;
|
|
};
|
|
|
|
void RunTestCaseWithPermutations(const TestCaseMoves* mapping,
|
|
intptr_t* insert_permutation,
|
|
intptr_t count) {
|
|
CatchEntryMovesMapBuilder b;
|
|
|
|
for (intptr_t i = 0; i < count; ++i) {
|
|
auto expected_moves = mapping[insert_permutation[i]];
|
|
b.NewMapping(/*pc_offset=*/insert_permutation[i]);
|
|
for (intptr_t j = 0; j < expected_moves.count; ++j) {
|
|
b.Append(expected_moves.moves[j]);
|
|
}
|
|
b.EndMapping();
|
|
}
|
|
|
|
const auto& bytes = TypedData::Handle(b.FinalizeCatchEntryMovesMap());
|
|
CatchEntryMovesMapReader reader(bytes);
|
|
|
|
for (intptr_t i = 0; i < count; ++i) {
|
|
auto expected_moves = mapping[i];
|
|
auto read_moves = reader.ReadMovesForPcOffset(i);
|
|
EXPECT_EQ(expected_moves.count, read_moves->count());
|
|
for (intptr_t j = 0; j < expected_moves.count; ++j) {
|
|
EXPECT(expected_moves.moves[j] == read_moves->At(j));
|
|
}
|
|
free(read_moves);
|
|
}
|
|
}
|
|
|
|
void RunTestCase(const TestCaseMoves* mapping, intptr_t count) {
|
|
std::unique_ptr<intptr_t[]> permutation(new intptr_t[count]);
|
|
for (intptr_t i = 0; i < count; ++i) {
|
|
permutation[i] = i;
|
|
}
|
|
|
|
std::function<void(intptr_t)> run_all_permutations = [&](intptr_t offset) {
|
|
if (offset == count) {
|
|
RunTestCaseWithPermutations(mapping, &permutation[0], count);
|
|
} else {
|
|
for (intptr_t i = offset; i < count; ++i) {
|
|
const intptr_t start = permutation[offset];
|
|
const intptr_t replacement = permutation[i];
|
|
|
|
permutation[offset] = replacement;
|
|
permutation[i] = start;
|
|
|
|
run_all_permutations(offset + 1);
|
|
|
|
permutation[offset] = start;
|
|
permutation[i] = replacement;
|
|
}
|
|
}
|
|
};
|
|
|
|
run_all_permutations(0);
|
|
}
|
|
|
|
ISOLATE_UNIT_TEST_CASE(CatchEntryMoves) {
|
|
// Common prefix.
|
|
const TestCaseMoves test1[] = {
|
|
TestCaseMoves{
|
|
abcde,
|
|
ARRAY_SIZE(abcde),
|
|
},
|
|
TestCaseMoves{
|
|
abcdx,
|
|
ARRAY_SIZE(abcdx),
|
|
},
|
|
};
|
|
RunTestCase(test1, ARRAY_SIZE(test1));
|
|
|
|
// Common suffix.
|
|
const TestCaseMoves test2[] = {
|
|
TestCaseMoves{
|
|
abcde,
|
|
ARRAY_SIZE(abcde),
|
|
},
|
|
TestCaseMoves{
|
|
xbcde,
|
|
ARRAY_SIZE(xbcde),
|
|
},
|
|
};
|
|
RunTestCase(test2, ARRAY_SIZE(test2));
|
|
|
|
// Common prefix and suffix.
|
|
const TestCaseMoves test3[] = {
|
|
TestCaseMoves{
|
|
abcde,
|
|
ARRAY_SIZE(abcde),
|
|
},
|
|
TestCaseMoves{
|
|
abxde,
|
|
ARRAY_SIZE(abxde),
|
|
},
|
|
};
|
|
RunTestCase(test3, ARRAY_SIZE(test3));
|
|
|
|
// Subset of suffix.
|
|
const TestCaseMoves test4[] = {
|
|
TestCaseMoves{
|
|
abcde,
|
|
ARRAY_SIZE(abcde),
|
|
},
|
|
TestCaseMoves{
|
|
de,
|
|
ARRAY_SIZE(de),
|
|
},
|
|
};
|
|
RunTestCase(test4, ARRAY_SIZE(test4));
|
|
|
|
// Subset of prefix.
|
|
const TestCaseMoves test5[] = {
|
|
TestCaseMoves{
|
|
abcde,
|
|
ARRAY_SIZE(abcde),
|
|
},
|
|
TestCaseMoves{
|
|
ab,
|
|
ARRAY_SIZE(ab),
|
|
},
|
|
};
|
|
RunTestCase(test5, ARRAY_SIZE(test5));
|
|
|
|
// All moves (with duplicates).
|
|
const TestCaseMoves test6[] = {
|
|
TestCaseMoves{
|
|
abcde,
|
|
ARRAY_SIZE(abcde),
|
|
},
|
|
TestCaseMoves{
|
|
abcde,
|
|
ARRAY_SIZE(abcde),
|
|
},
|
|
TestCaseMoves{
|
|
abcdx,
|
|
ARRAY_SIZE(abcdx),
|
|
},
|
|
TestCaseMoves{
|
|
xbcde,
|
|
ARRAY_SIZE(xbcde),
|
|
},
|
|
TestCaseMoves{
|
|
abxde,
|
|
ARRAY_SIZE(abxde),
|
|
},
|
|
TestCaseMoves{
|
|
ab,
|
|
ARRAY_SIZE(ab),
|
|
},
|
|
TestCaseMoves{
|
|
de,
|
|
ARRAY_SIZE(de),
|
|
},
|
|
TestCaseMoves{
|
|
de,
|
|
ARRAY_SIZE(de),
|
|
},
|
|
};
|
|
RunTestCase(test6, ARRAY_SIZE(test6));
|
|
}
|
|
|
|
} // namespace dart
|