Add field evaluation to source report generation
Change-Id: I62808852a35ef53c05ac1ea715d4559db46bb3d5
Reviewed-on: https://dart-review.googlesource.com/c/89173
Commit-Queue: Zichang Guo <zichangguo@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
diff --git a/runtime/observatory/tests/service/get_source_report_test.dart b/runtime/observatory/tests/service/get_source_report_test.dart
index ce2fa5b3..f8dbfaaa 100644
--- a/runtime/observatory/tests/service/get_source_report_test.dart
+++ b/runtime/observatory/tests/service/get_source_report_test.dart
@@ -78,9 +78,9 @@
final numRanges = coverage['ranges'].length;
expect(coverage['type'], equals('SourceReport'));
- // Running in app_jitk mode will result in the number of ranges being 6
- // during the training run and 7 when running from the snapshot.
- expect(((numRanges == 6) || (numRanges == 7)), isTrue);
+ // Running in app_jitk mode will result in the number of ranges being 7
+ // during the training run and 8 when running from the snapshot.
+ expect(((numRanges == 7) || (numRanges == 8)), isTrue);
expect(coverage['ranges'][0], equals(expectedRange));
expect(coverage['scripts'].length, 1);
expect(
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 0a1a227..753a7c3 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -2789,17 +2789,11 @@
if (!field.has_initializer()) {
continue;
}
-
- bool has_func_literal_initializer = false;
-#ifndef DART_PRECOMPILED_RUNTIME
- has_func_literal_initializer =
- kernel::FieldHasFunctionLiteralInitializer(field, &start, &end);
-#endif // !DART_PRECOMPILED_RUNTIME
- if (has_func_literal_initializer) {
- if ((start <= token_pos && token_pos <= end) ||
- (token_pos <= start && start <= last_token_pos)) {
- return true;
- }
+ start = field.token_pos();
+ end = field.end_token_pos();
+ if ((start <= token_pos && token_pos <= end) ||
+ (token_pos <= start && start <= last_token_pos)) {
+ return true;
}
}
}
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index da7a69c..f9a3850 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -3036,6 +3036,7 @@
return true;
}
+#if !defined(DART_PRECOMPILED_RUNTIME)
static const char* const report_enum_names[] = {
SourceReport::kCallSitesStr,
SourceReport::kCoverageStr,
@@ -3043,18 +3044,25 @@
SourceReport::kProfileStr,
NULL,
};
+#endif
static const MethodParameter* get_source_report_params[] = {
+#if !defined(DART_PRECOMPILED_RUNTIME)
RUNNABLE_ISOLATE_PARAMETER,
new EnumListParameter("reports", true, report_enum_names),
new IdParameter("scriptId", false),
new UIntParameter("tokenPos", false),
new UIntParameter("endTokenPos", false),
new BoolParameter("forceCompile", false),
+#endif
NULL,
};
static bool GetSourceReport(Thread* thread, JSONStream* js) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ js->PrintError(kFeatureDisabled, "disabled in AOT mode and PRODUCT.");
+ return false;
+#else
if (CheckCompilerDisabled(thread, js)) {
return true;
}
@@ -3116,6 +3124,7 @@
report.PrintJSON(js, script, TokenPosition(start_pos),
TokenPosition(end_pos));
return true;
+#endif // !DART_PRECOMPILED_RUNTIME
}
static const MethodParameter* reload_sources_params[] = {
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 7ce25de..a1e3da2 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -1,11 +1,13 @@
// Copyright (c) 2015, 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.
-#ifndef PRODUCT
+#include "vm/globals.h"
+#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/source_report.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/isolate.h"
+#include "vm/kernel_loader.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/profiler.h"
@@ -90,6 +92,7 @@
case RawFunction::kRegularFunction:
case RawFunction::kClosureFunction:
case RawFunction::kImplicitClosureFunction:
+ case RawFunction::kImplicitStaticFinalGetter:
case RawFunction::kGetterFunction:
case RawFunction::kSetterFunction:
case RawFunction::kConstructor:
@@ -111,6 +114,28 @@
return false;
}
+bool SourceReport::ShouldSkipField(const Field& field) {
+ if (!field.token_pos().IsReal() || !field.end_token_pos().IsReal()) {
+ // At least one of the token positions is not known.
+ return true;
+ }
+
+ if (script_ != NULL && !script_->IsNull()) {
+ if (field.Script() != script_->raw()) {
+ // The field is from the wrong script.
+ return true;
+ }
+ if (((start_pos_ > TokenPosition::kMinSource) &&
+ (field.end_token_pos() < start_pos_)) ||
+ ((end_pos_ > TokenPosition::kMinSource) &&
+ (field.token_pos() > end_pos_))) {
+ // The field does not intersect with the requested token range.
+ return true;
+ }
+ }
+ return false;
+}
+
intptr_t SourceReport::GetScriptIndex(const Script& script) {
ScriptTableEntry wrapper;
const String& url = String::Handle(zone(), script.url());
@@ -465,10 +490,25 @@
}
}
+void SourceReport::VisitField(JSONArray* jsarr, const Field& field) {
+ if (ShouldSkipField(field) || !field.has_initializer()) return;
+ const Function& func =
+ Function::Handle(zone(), GetInitializerFunction(field));
+ VisitFunction(jsarr, func);
+}
+
+RawFunction* SourceReport::GetInitializerFunction(const Field& field) {
+ Thread* const thread = Thread::Current();
+ // Create a function to evaluate the initializer
+ return kernel::CreateFieldInitializerFunction(thread, thread->zone(), field);
+}
+
void SourceReport::VisitLibrary(JSONArray* jsarr, const Library& lib) {
Class& cls = Class::Handle(zone());
Array& functions = Array::Handle(zone());
+ Array& fields = Array::Handle(zone());
Function& func = Function::Handle(zone());
+ Field& field = Field::Handle(zone());
Script& script = Script::Handle(zone());
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
@@ -505,6 +545,12 @@
func ^= functions.At(i);
VisitFunction(jsarr, func);
}
+
+ fields = cls.fields();
+ for (intptr_t i = 0; i < fields.Length(); i++) {
+ field ^= fields.At(i);
+ VisitField(jsarr, field);
+ }
}
}
@@ -554,4 +600,4 @@
}
} // namespace dart
-#endif // PRODUCT
+#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/source_report.h b/runtime/vm/source_report.h
index 5ab147f..73a9c3d 100644
--- a/runtime/vm/source_report.h
+++ b/runtime/vm/source_report.h
@@ -5,6 +5,9 @@
#ifndef RUNTIME_VM_SOURCE_REPORT_H_
#define RUNTIME_VM_SOURCE_REPORT_H_
+#include "vm/globals.h"
+#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+
#include "vm/allocation.h"
#include "vm/flags.h"
#include "vm/hash_map.h"
@@ -60,6 +63,7 @@
bool IsReportRequested(ReportKind report_kind);
bool ShouldSkipFunction(const Function& func);
+ bool ShouldSkipField(const Field& field);
intptr_t GetScriptIndex(const Script& script);
bool ScriptIsLoadedByLibrary(const Script& script, const Library& lib);
@@ -79,9 +83,10 @@
void PrintScriptTable(JSONArray* jsarr);
void VisitFunction(JSONArray* jsarr, const Function& func);
+ void VisitField(JSONArray* jsarr, const Field& field);
void VisitLibrary(JSONArray* jsarr, const Library& lib);
void VisitClosures(JSONArray* jsarr);
-
+ RawFunction* GetInitializerFunction(const Field& field);
// An entry in the script table.
struct ScriptTableEntry {
ScriptTableEntry() : key(NULL), index(-1), script(NULL) {}
@@ -122,4 +127,5 @@
} // namespace dart
+#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
#endif // RUNTIME_VM_SOURCE_REPORT_H_