ed64348f68
This CL introduces an alternative way to calculate scopes for expression evaluations. Currently the previous method is kept as well. What this does is that it: * Finds all nodes that match the offset and uri. (Ideally there's only one, but that's not always the case --- it's the case for less than 60% of cases in the test added actually). * Calculate the scope along the way. * Return the scopes of all the found nodes that offset. A test that asks for ~all file offsets in the dill files in the sdk and compares the result with the scope the binary serialization computes is added. A single point can't always be found (for all dills in the sdk only ~58.93% returns a single result), but for each query the wanted scope is among the results returned. For the non-outline dills in the sdk, between ~87.93% and ~94.52% of the results are either a single result or multiple results with the same actual scope in all of them. Note that the test asks for ~all offsets, not just "debuggable" or "stopable" offsets (which will likely vary depending on the vm/web backend etc) --- likely the percentage will be higher for those points though. When this returns multiple results one can likely be picked by the client based on information it has about names of variables in scope etc. Note that the test is rather slow, on my machine with the platforms available there it makes 3,908,181 queries in ~3.5 minutes. (Which corresponds to roughly 18,610 per second or under 0.06 ms per query on average though, so it doesn't seem like a concert for actually using it.) Change-Id: I40b5360fcd935c70629543737e89a787de36ca16 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/332204 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Jens Johansen <jensj@google.com>
100 lines
2.8 KiB
Dart
100 lines
2.8 KiB
Dart
// Copyright (c) 2023, 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.
|
|
|
|
import 'dart:io';
|
|
|
|
/// Finds unique dills in the sdk.
|
|
///
|
|
/// Note that it reads all dills found to create and compare a checksum to
|
|
/// remove duplicates (and re-read on checksum matches).
|
|
List<File> findSdkDills() {
|
|
File exe = new File(Platform.resolvedExecutable).absolute;
|
|
int steps = 0;
|
|
Directory parent = exe.parent.parent;
|
|
while (true) {
|
|
Set<String> foundDirs = {};
|
|
for (FileSystemEntity entry in parent.listSync(recursive: false)) {
|
|
if (entry is Directory) {
|
|
List<String> pathSegments = entry.uri.pathSegments;
|
|
String name = pathSegments[pathSegments.length - 2];
|
|
foundDirs.add(name);
|
|
}
|
|
}
|
|
if (foundDirs.contains("pkg") &&
|
|
foundDirs.contains("tools") &&
|
|
foundDirs.contains("tests")) {
|
|
break;
|
|
}
|
|
steps++;
|
|
if (parent.uri == parent.parent.uri) {
|
|
throw "Reached end without finding the root.";
|
|
}
|
|
parent = parent.parent;
|
|
}
|
|
// We had to go $steps steps to reach the "root" --- now we should go 2 steps
|
|
// shorter to be in the "compiled dir".
|
|
parent = exe.parent;
|
|
for (int i = steps - 2; i >= 0; i--) {
|
|
parent = parent.parent;
|
|
}
|
|
|
|
List<File> dills = [];
|
|
List<int> checksums = [];
|
|
for (FileSystemEntity entry in parent.listSync(recursive: false)) {
|
|
if (entry is File) {
|
|
if (entry.path.toLowerCase().endsWith(".dill")) {
|
|
_addIfNotDuplicate(entry, dills, checksums);
|
|
}
|
|
}
|
|
}
|
|
Directory sdk = new Directory.fromUri(parent.uri.resolve("dart-sdk/"));
|
|
for (FileSystemEntity entry in sdk.listSync(recursive: true)) {
|
|
if (entry is File) {
|
|
if (entry.path.toLowerCase().endsWith(".dill")) {
|
|
_addIfNotDuplicate(entry, dills, checksums);
|
|
}
|
|
}
|
|
}
|
|
return dills;
|
|
}
|
|
|
|
void _addIfNotDuplicate(File f, List<File> existingFiles, List<int> checksums) {
|
|
List<int> content = f.readAsBytesSync();
|
|
int adler = adler32(content);
|
|
for (int i = 0; i < checksums.length; i++) {
|
|
if (checksums[i] == adler) {
|
|
List<int> existingContent = existingFiles[i].readAsBytesSync();
|
|
bool duplicate = existingContent.length == content.length;
|
|
if (duplicate) {
|
|
for (int j = 0; j < existingContent.length; j++) {
|
|
if (existingContent[j] != content[j]) {
|
|
duplicate = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (duplicate) return;
|
|
}
|
|
}
|
|
checksums.add(adler);
|
|
existingFiles.add(f);
|
|
}
|
|
|
|
int adler32(List<int> data) {
|
|
int a = 1;
|
|
int b = 0;
|
|
for (int i = 0; i < data.length; i++) {
|
|
a += data[i];
|
|
b += a;
|
|
|
|
if (i & 255 == 255) {
|
|
a %= 65521;
|
|
b %= 65521;
|
|
}
|
|
}
|
|
a %= 65521;
|
|
b %= 65521;
|
|
return (b << 16) | a;
|
|
}
|