mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 14:07:57 +00:00
[kernel] Allow collection of token positions for unfinalized classes
E.g. ``` main() { new Foo(); } class Foo { Foo() { print("hello from foo"); } } ``` debugging with --pause_isolates_on_start, the constructor (or anything else in class Foo) would not be breakable from the Observatory interface. This CL fixes that by collecting token positions from unfinalized classes. Bug: Change-Id: I93a20f3322b0a343a619625c71236b59c885cb7e Reviewed-on: https://dart-review.googlesource.com/30441 Commit-Queue: Jens Johansen <jensj@google.com> Reviewed-by: Vyacheslav Egorov <vegorov@google.com> Reviewed-by: Kevin Millikin <kmillikin@google.com>
This commit is contained in:
parent
2eab494036
commit
45a59597fc
|
@ -9207,6 +9207,9 @@ void StreamingFlowGraphBuilder::CollectTokenPositionsFor(
|
|||
} else if (tag == kField) {
|
||||
FieldHelper field_helper(this);
|
||||
field_helper.ReadUntilExcluding(FieldHelper::kEnd);
|
||||
} else if (tag == kClass) {
|
||||
ClassHelper class_helper(this);
|
||||
class_helper.ReadUntilExcluding(ClassHelper::kEnd);
|
||||
} else {
|
||||
H.ReportError("Unsupported tag at this point: %d.", tag);
|
||||
UNREACHABLE();
|
||||
|
|
|
@ -2676,35 +2676,53 @@ void CollectTokenPositionsFor(const Script& const_script) {
|
|||
if (entry.IsClass()) {
|
||||
const Class& klass = Class::Cast(entry);
|
||||
entry_script = klass.script();
|
||||
if (!entry_script.IsNull() && script.kernel_script_index() ==
|
||||
entry_script.kernel_script_index()) {
|
||||
if (!entry_script.IsNull() &&
|
||||
(script.kernel_script_index() ==
|
||||
entry_script.kernel_script_index()) &&
|
||||
(script.kernel_string_offsets() ==
|
||||
entry_script.kernel_string_offsets())) {
|
||||
token_positions.Add(klass.token_pos().value());
|
||||
}
|
||||
Array& array = Array::Handle(zone_, klass.fields());
|
||||
Field& field = Field::Handle(Z);
|
||||
for (intptr_t i = 0; i < array.Length(); ++i) {
|
||||
field ^= array.At(i);
|
||||
if (field.kernel_offset() <= 0) {
|
||||
// Skip artificially injected fields.
|
||||
continue;
|
||||
if (klass.is_finalized()) {
|
||||
Array& array = Array::Handle(Z, klass.fields());
|
||||
Field& field = Field::Handle(Z);
|
||||
for (intptr_t i = 0; i < array.Length(); ++i) {
|
||||
field ^= array.At(i);
|
||||
if (field.kernel_offset() <= 0) {
|
||||
// Skip artificially injected fields.
|
||||
continue;
|
||||
}
|
||||
data = field.KernelData();
|
||||
entry_script = field.Script();
|
||||
ProcessTokenPositionsEntry(
|
||||
data, script, entry_script, field.kernel_offset(),
|
||||
field.KernelDataProgramOffset(), Z, &helper, &token_positions,
|
||||
&yield_positions);
|
||||
}
|
||||
data = field.KernelData();
|
||||
entry_script = field.Script();
|
||||
ProcessTokenPositionsEntry(
|
||||
data, script, entry_script, field.kernel_offset(),
|
||||
field.KernelDataProgramOffset(), zone_, &helper, &token_positions,
|
||||
&yield_positions);
|
||||
}
|
||||
array = klass.functions();
|
||||
Function& function = Function::Handle(Z);
|
||||
for (intptr_t i = 0; i < array.Length(); ++i) {
|
||||
function ^= array.At(i);
|
||||
data = function.KernelData();
|
||||
entry_script = function.script();
|
||||
ProcessTokenPositionsEntry(
|
||||
data, script, entry_script, function.kernel_offset(),
|
||||
function.KernelDataProgramOffset(), zone_, &helper,
|
||||
&token_positions, &yield_positions);
|
||||
array = klass.functions();
|
||||
Function& function = Function::Handle(Z);
|
||||
for (intptr_t i = 0; i < array.Length(); ++i) {
|
||||
function ^= array.At(i);
|
||||
data = function.KernelData();
|
||||
entry_script = function.script();
|
||||
ProcessTokenPositionsEntry(
|
||||
data, script, entry_script, function.kernel_offset(),
|
||||
function.KernelDataProgramOffset(), Z, &helper,
|
||||
&token_positions, &yield_positions);
|
||||
}
|
||||
} else {
|
||||
// Class isn't finalized yet: read the data attached to it.
|
||||
ASSERT(klass.kernel_offset() > 0);
|
||||
data = lib.kernel_data();
|
||||
ASSERT(!data.IsNull());
|
||||
const intptr_t library_kernel_offset = lib.kernel_offset();
|
||||
ASSERT(library_kernel_offset > 0);
|
||||
const intptr_t class_offset = klass.kernel_offset();
|
||||
|
||||
entry_script = klass.script();
|
||||
ProcessTokenPositionsEntry(data, script, entry_script, class_offset,
|
||||
library_kernel_offset, Z, &helper,
|
||||
&token_positions, &yield_positions);
|
||||
}
|
||||
} else if (entry.IsFunction()) {
|
||||
const Function& function = Function::Cast(entry);
|
||||
|
@ -2712,7 +2730,7 @@ void CollectTokenPositionsFor(const Script& const_script) {
|
|||
entry_script = function.script();
|
||||
ProcessTokenPositionsEntry(data, script, entry_script,
|
||||
function.kernel_offset(),
|
||||
function.KernelDataProgramOffset(), zone_,
|
||||
function.KernelDataProgramOffset(), Z,
|
||||
&helper, &token_positions, &yield_positions);
|
||||
} else if (entry.IsField()) {
|
||||
const Field& field = Field::Cast(entry);
|
||||
|
@ -2724,8 +2742,8 @@ void CollectTokenPositionsFor(const Script& const_script) {
|
|||
entry_script = field.Script();
|
||||
ProcessTokenPositionsEntry(data, script, entry_script,
|
||||
field.kernel_offset(),
|
||||
field.KernelDataProgramOffset(), zone_,
|
||||
&helper, &token_positions, &yield_positions);
|
||||
field.KernelDataProgramOffset(), Z, &helper,
|
||||
&token_positions, &yield_positions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3565,16 +3565,37 @@ void Class::set_token_pos(TokenPosition token_pos) const {
|
|||
}
|
||||
|
||||
TokenPosition Class::ComputeEndTokenPos() const {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
return TokenPosition::kNoSource;
|
||||
#else
|
||||
// Return the begin token for synthetic classes.
|
||||
if (is_synthesized_class() || IsMixinApplication() || IsTopLevel()) {
|
||||
return token_pos();
|
||||
}
|
||||
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
const Script& scr = Script::Handle(zone, script());
|
||||
ASSERT(!scr.IsNull());
|
||||
|
||||
if (scr.kind() == RawScript::kKernelTag) {
|
||||
ASSERT(kernel_offset() > 0);
|
||||
const Library& lib = Library::Handle(zone, library());
|
||||
const TypedData& kernel_data = TypedData::Handle(zone, lib.kernel_data());
|
||||
ASSERT(!kernel_data.IsNull());
|
||||
const intptr_t library_kernel_offset = lib.kernel_offset();
|
||||
ASSERT(library_kernel_offset > 0);
|
||||
const intptr_t class_offset = kernel_offset();
|
||||
|
||||
kernel::TranslationHelper helper(thread);
|
||||
helper.InitFromScript(scr);
|
||||
kernel::StreamingFlowGraphBuilder builder_(&helper, scr, zone, kernel_data,
|
||||
0);
|
||||
builder_.SetOffset(class_offset);
|
||||
kernel::ClassHelper class_helper(&builder_);
|
||||
class_helper.ReadUntilIncluding(kernel::ClassHelper::kEndPosition);
|
||||
if (class_helper.end_position_.IsReal()) return class_helper.end_position_;
|
||||
|
||||
TokenPosition largest_seen = token_pos();
|
||||
|
||||
// Walk through all functions and get their end_tokens to find the classes
|
||||
|
@ -3613,6 +3634,7 @@ TokenPosition Class::ComputeEndTokenPos() const {
|
|||
}
|
||||
UNREACHABLE();
|
||||
return TokenPosition::kNoSource;
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t Class::SourceFingerprint() const {
|
||||
|
|
Loading…
Reference in a new issue