[vm] Remove non-private uses of TokenPosition::value().
Instead, split each old use into the following cases: * If the TokenPosition value is expected to be a real token position, then use TokenPosition::Pos(). * If the TokenPosition is being serialized in some way, then use TokenPosition::Serialize() and change the place where the TokenPosition is recreated to use TokenPosition::Deserialize(). * If the value of the TokenPosition is being printed for debugging purposes, then just use TokenPosition::ToCString() instead. That is, we try to pin down when token positions are expected to be real vs. when other types of token positions can be found. Another source of possible error when using token positions is to convert between synthetic and real token positions. In the past, synthetic token positions may have been based off real token positions, but that is no longer the case. Thus, all methods that allow that conversion have been removed, and instead there is a new static method for constructing synthetic tokens from valid nonces. This CL also makes it so that Pos() and relational operators on token positions are only defined on real token positions, to avoid any assumptions about what the value encoded in synthetic positions mean. To help with cases where non-real token positions may occur, four helper methods are added: * TokenPosition::Min(a, b): A static method that returns the smallest real token position provided. If neither `a` or `b` are real, returns `a`. * TokenPosition::Max(a, b): A static method that returns the largest real token position provided. If neither `a` or `b` are real, returns `a`. * TokenPosition::IsWithin(start, end): Determines whether `this` falls between `start` and `end` (inclusive). If `this` is non-real, then it must be either `start` or `end` if synthetic, otherwise false. Otherwise, we mimic the old style of range checking, which means that non-real starts and ends are treated as less than every real token. * TokenPosition::CompareForSorting(other): Unlike the relational operators, provides a comparison between any types of token positions for purposes such as sorting. Currently only used in the profiler. It also changes TokenPosition::ToCString() to tag synthetic token positions, so they can be distinguished from real ones at a glance. TEST=Existing test suite on trybots, especially the observatory tests which make heavy use of the debugger and the unit tests for the profiler/source report modules. Bug: https://github.com/dart-lang/sdk/issues/44436 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-linux-debug-x64-try,vm-kernel-linux-release-x64-try,vm-kernel-nnbd-linux-release-x64-try,vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-nnbd-linux-release-x64-try,vm-kernel-linux-product-x64-try,vm-kernel-precomp-linux-product-x64-try Change-Id: Ic06aa0bc7a1f0fbac7257ed22ca5e7e0ccd7f3f2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/174924 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
ac18a7ba91
commit
e2df4d30a0
@@ -67,9 +67,9 @@ static ScriptPtr FindScript(DartFrameIterator* iterator) {
|
||||
DEFINE_NATIVE_ENTRY(AssertionError_throwNew, 0, 3) {
|
||||
// No need to type check the arguments. This function can only be called
|
||||
// internally from the VM.
|
||||
const TokenPosition assertion_start = TokenPosition(
|
||||
const TokenPosition assertion_start = TokenPosition::Deserialize(
|
||||
Smi::CheckedHandle(zone, arguments->NativeArgAt(0)).Value());
|
||||
const TokenPosition assertion_end = TokenPosition(
|
||||
const TokenPosition assertion_end = TokenPosition::Deserialize(
|
||||
Smi::CheckedHandle(zone, arguments->NativeArgAt(1)).Value());
|
||||
|
||||
const Instance& message =
|
||||
@@ -151,7 +151,7 @@ DEFINE_NATIVE_ENTRY(AssertionError_throwNewSource, 0, 4) {
|
||||
DEFINE_NATIVE_ENTRY(TypeError_throwNew, 0, 4) {
|
||||
// No need to type check the arguments. This function can only be called
|
||||
// internally from the VM.
|
||||
const TokenPosition location = TokenPosition(
|
||||
const TokenPosition location = TokenPosition::Deserialize(
|
||||
Smi::CheckedHandle(zone, arguments->NativeArgAt(0)).Value());
|
||||
const Instance& src_value =
|
||||
Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
|
||||
@@ -171,7 +171,7 @@ DEFINE_NATIVE_ENTRY(TypeError_throwNew, 0, 4) {
|
||||
// Return value: none, throws an exception.
|
||||
DEFINE_NATIVE_ENTRY(FallThroughError_throwNew, 0, 1) {
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
|
||||
TokenPosition fallthrough_pos = TokenPosition(smi_pos.Value());
|
||||
TokenPosition fallthrough_pos = TokenPosition::Deserialize(smi_pos.Value());
|
||||
|
||||
const Array& args = Array::Handle(Array::New(2));
|
||||
|
||||
@@ -197,7 +197,7 @@ DEFINE_NATIVE_ENTRY(FallThroughError_throwNew, 0, 1) {
|
||||
DEFINE_NATIVE_ENTRY(AbstractClassInstantiationError_throwNew, 0, 2) {
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(String, class_name, arguments->NativeArgAt(1));
|
||||
TokenPosition error_pos = TokenPosition(smi_pos.Value());
|
||||
TokenPosition error_pos = TokenPosition::Deserialize(smi_pos.Value());
|
||||
|
||||
const Array& args = Array::Handle(Array::New(3));
|
||||
|
||||
|
||||
@@ -447,7 +447,7 @@ DEFINE_NATIVE_ENTRY(Internal_boundsCheckForPartialInstantiation, 0, 2) {
|
||||
if (!AbstractType::InstantiateAndTestSubtype(
|
||||
&subtype, &supertype, instantiator_type_args, function_type_args)) {
|
||||
// Throw a dynamic type error.
|
||||
TokenPosition location;
|
||||
TokenPosition location = TokenPosition::kNoSource;
|
||||
{
|
||||
DartFrameIterator iterator(Thread::Current(),
|
||||
StackFrameIterator::kNoCrossThreadIteration);
|
||||
|
||||
@@ -53,15 +53,19 @@ Future testAsync(Isolate isolate) async {
|
||||
var script = isolate.rootLibrary.scripts[0];
|
||||
|
||||
var bp1 = await isolate.addBreakpoint(script, 13);
|
||||
print("BP1 - $bp1");
|
||||
expect(bp1, isNotNull);
|
||||
expect(bp1 is Breakpoint, isTrue);
|
||||
var bp2 = await isolate.addBreakpoint(script, 18);
|
||||
print("BP2 - $bp2");
|
||||
expect(bp2, isNotNull);
|
||||
expect(bp2 is Breakpoint, isTrue);
|
||||
var bp3 = await isolate.addBreakpoint(script, 23);
|
||||
print("BP3 - $bp3");
|
||||
expect(bp3, isNotNull);
|
||||
expect(bp3 is Breakpoint, isTrue);
|
||||
var bp4 = await isolate.addBreakpoint(script, 27);
|
||||
print("BP4 - $bp4");
|
||||
expect(bp4, isNotNull);
|
||||
expect(bp4 is Breakpoint, isTrue);
|
||||
var bp5 = await isolate.addBreakpoint(script, 44);
|
||||
|
||||
@@ -23,6 +23,10 @@ process_service_test: Pass, Fail # Issue 24344
|
||||
developer_extension_test: SkipByDesign
|
||||
get_isolate_after_language_error_test: SkipByDesign
|
||||
|
||||
# The _1 versions of this test can be slow due to stress testing flags.
|
||||
[ $mode == debug ]
|
||||
async_generator_breakpoint_test: Pass, Slow
|
||||
|
||||
# Service protocol is not supported in product mode.
|
||||
[ $mode == product ]
|
||||
*: SkipByDesign
|
||||
|
||||
@@ -53,15 +53,19 @@ Future testAsync(Isolate isolate) async {
|
||||
var script = isolate.rootLibrary.scripts[0];
|
||||
|
||||
var bp1 = await isolate.addBreakpoint(script, 13);
|
||||
print("BP1 - $bp1");
|
||||
expect(bp1, isNotNull);
|
||||
expect(bp1 is Breakpoint, isTrue);
|
||||
var bp2 = await isolate.addBreakpoint(script, 18);
|
||||
print("BP2 - $bp2");
|
||||
expect(bp2, isNotNull);
|
||||
expect(bp2 is Breakpoint, isTrue);
|
||||
var bp3 = await isolate.addBreakpoint(script, 23);
|
||||
print("BP3 - $bp3");
|
||||
expect(bp3, isNotNull);
|
||||
expect(bp3 is Breakpoint, isTrue);
|
||||
var bp4 = await isolate.addBreakpoint(script, 27);
|
||||
print("BP4 - $bp4");
|
||||
expect(bp4, isNotNull);
|
||||
expect(bp4 is Breakpoint, isTrue);
|
||||
var bp5 = await isolate.addBreakpoint(script, 44);
|
||||
|
||||
@@ -25,6 +25,10 @@ dominator_tree_vm_with_double_field_test: SkipByDesign
|
||||
developer_extension_test: SkipByDesign
|
||||
get_isolate_after_language_error_test: SkipByDesign
|
||||
|
||||
# The _1 versions of this test can be slow due to stress testing flags.
|
||||
[ $mode == debug ]
|
||||
async_generator_breakpoint_test: Pass, Slow
|
||||
|
||||
# Service protocol is not supported in product mode.
|
||||
[ $mode == product ]
|
||||
*: SkipByDesign
|
||||
|
||||
@@ -340,9 +340,7 @@ class Serializer : public ThreadStackResource {
|
||||
}
|
||||
}
|
||||
|
||||
void WriteTokenPosition(TokenPosition pos) {
|
||||
Write<int32_t>(pos.SnapshotEncode());
|
||||
}
|
||||
void WriteTokenPosition(TokenPosition pos) { Write(pos.Serialize()); }
|
||||
|
||||
void WriteCid(intptr_t cid) {
|
||||
COMPILE_ASSERT(ObjectLayout::kClassIdTagSize <= 32);
|
||||
@@ -616,7 +614,7 @@ class Deserializer : public ThreadStackResource {
|
||||
}
|
||||
|
||||
TokenPosition ReadTokenPosition() {
|
||||
return TokenPosition::SnapshotDecode(Read<int32_t>());
|
||||
return TokenPosition::Deserialize(Read<int32_t>());
|
||||
}
|
||||
|
||||
intptr_t ReadCid() {
|
||||
|
||||
@@ -40,10 +40,11 @@ void DescriptorList::AddDescriptor(PcDescriptorsLayout::Kind kind,
|
||||
prev_pc_offset = pc_offset;
|
||||
|
||||
if (!FLAG_precompiled_mode) {
|
||||
const int32_t encoded_pos = token_pos.Serialize();
|
||||
encoded_data_.WriteSLEB128(deopt_id - prev_deopt_id);
|
||||
encoded_data_.WriteSLEB128(token_pos.value() - prev_token_pos);
|
||||
encoded_data_.WriteSLEB128(encoded_pos - prev_token_pos);
|
||||
prev_deopt_id = deopt_id;
|
||||
prev_token_pos = token_pos.value();
|
||||
prev_token_pos = encoded_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,8 +198,8 @@ TypedDataPtr CatchEntryMovesMapBuilder::FinalizeCatchEntryMovesMap() {
|
||||
}
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
const TokenPosition CodeSourceMapBuilder::kInitialPosition =
|
||||
TokenPosition(TokenPosition::kDartCodeProloguePos);
|
||||
const TokenPosition& CodeSourceMapBuilder::kInitialPosition =
|
||||
TokenPosition::kDartCodePrologue;
|
||||
|
||||
CodeSourceMapBuilder::CodeSourceMapBuilder(
|
||||
Zone* zone,
|
||||
@@ -311,7 +312,7 @@ void CodeSourceMapBuilder::StartInliningInterval(int32_t pc_offset,
|
||||
}
|
||||
for (intptr_t i = to_push.length() - 1; i >= 0; i--) {
|
||||
intptr_t callee_id = to_push[i];
|
||||
TokenPosition call_token;
|
||||
TokenPosition call_token = TokenPosition::kNoSource;
|
||||
if (callee_id != 0) {
|
||||
// TODO(rmacnak): Should make this array line up with the others.
|
||||
call_token = inline_id_to_token_pos_[callee_id - 1];
|
||||
@@ -396,20 +397,19 @@ CodeSourceMapPtr CodeSourceMapBuilder::Finalize() {
|
||||
|
||||
void CodeSourceMapBuilder::WriteChangePosition(TokenPosition pos) {
|
||||
stream_.Write<uint8_t>(kChangePosition);
|
||||
intptr_t position_or_line = pos.value();
|
||||
intptr_t position_or_line = pos.Serialize();
|
||||
#if defined(DART_PRECOMPILER)
|
||||
intptr_t column = TokenPosition::kNoSourcePos;
|
||||
intptr_t column = TokenPosition::kNoSource.Serialize();
|
||||
if (FLAG_precompiled_mode) {
|
||||
// Don't use the raw position value directly in precompiled mode. Instead,
|
||||
// use the value of kNoSource as a fallback when no line or column
|
||||
// information is found.
|
||||
position_or_line = TokenPosition::kNoSourcePos;
|
||||
position_or_line = TokenPosition::kNoSource.Serialize();
|
||||
intptr_t inline_id = buffered_inline_id_stack_.Last();
|
||||
if (inline_id < inline_id_to_function_.length()) {
|
||||
const Function* function = inline_id_to_function_[inline_id];
|
||||
Script& script = Script::Handle(function->script());
|
||||
script.GetTokenLocationUsingLineStarts(pos.SourcePosition(),
|
||||
&position_or_line, &column);
|
||||
script.GetTokenLocation(pos, &position_or_line, &column);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -619,8 +619,8 @@ void CodeSourceMapReader::DumpSourcePositions(uword start) {
|
||||
THR_Print("%" Px "-%" Px ": ", start + current_pc_offset,
|
||||
start + current_pc_offset + delta - 1);
|
||||
for (intptr_t i = 0; i < function_stack.length(); i++) {
|
||||
THR_Print("%s@%" Pd " ", function_stack[i]->ToCString(),
|
||||
token_positions[i].value());
|
||||
THR_Print("%s@%s", function_stack[i]->ToCString(),
|
||||
token_positions[i].ToCString());
|
||||
}
|
||||
THR_Print("\n");
|
||||
current_pc_offset += delta;
|
||||
@@ -698,7 +698,8 @@ intptr_t CodeSourceMapReader::GetNullCheckNameIndexAt(int32_t pc_offset) {
|
||||
}
|
||||
|
||||
TokenPosition CodeSourceMapReader::ReadPosition(ReadStream* stream) {
|
||||
const intptr_t line = stream->Read<int32_t>();
|
||||
const TokenPosition line =
|
||||
TokenPosition::Deserialize(stream->Read<int32_t>());
|
||||
#if defined(DART_PRECOMPILER)
|
||||
// The special handling for non-symbolic stack trace mode only needs to
|
||||
// happen in the precompiler, because those CSMs are not serialized in
|
||||
@@ -707,7 +708,7 @@ TokenPosition CodeSourceMapReader::ReadPosition(ReadStream* stream) {
|
||||
stream->Read<int32_t>(); // Discard the column information.
|
||||
}
|
||||
#endif
|
||||
return TokenPosition(line);
|
||||
return line;
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
||||
@@ -42,7 +42,7 @@ class DescriptorList : public ZoneAllocated {
|
||||
|
||||
intptr_t prev_pc_offset;
|
||||
intptr_t prev_deopt_id;
|
||||
intptr_t prev_token_pos;
|
||||
int32_t prev_token_pos;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DescriptorList);
|
||||
};
|
||||
@@ -186,7 +186,7 @@ class CodeSourceMapBuilder : public ZoneAllocated {
|
||||
// The position at which a function implicitly starts, for both the root and
|
||||
// after a push bytecode. We use the classifying position kDartCodePrologue
|
||||
// since it is the most common.
|
||||
static const TokenPosition kInitialPosition;
|
||||
static const TokenPosition& kInitialPosition;
|
||||
|
||||
static const uint8_t kChangePosition = 0;
|
||||
static const uint8_t kAdvancePC = 1;
|
||||
|
||||
@@ -123,7 +123,7 @@ TEST_CASE(StackMapGC) {
|
||||
ISOLATE_UNIT_TEST_CASE(DescriptorList_TokenPositions) {
|
||||
DescriptorList* descriptors = new DescriptorList(thread->zone());
|
||||
ASSERT(descriptors != NULL);
|
||||
const intptr_t token_positions[] = {
|
||||
const int32_t token_positions[] = {
|
||||
kMinInt32,
|
||||
5,
|
||||
13,
|
||||
@@ -141,12 +141,12 @@ ISOLATE_UNIT_TEST_CASE(DescriptorList_TokenPositions) {
|
||||
TokenPosition::kMinSourcePos,
|
||||
TokenPosition::kMaxSourcePos,
|
||||
};
|
||||
const intptr_t num_token_positions =
|
||||
sizeof(token_positions) / sizeof(token_positions[0]);
|
||||
const intptr_t num_token_positions = ARRAY_SIZE(token_positions);
|
||||
|
||||
for (intptr_t i = 0; i < num_token_positions; i++) {
|
||||
descriptors->AddDescriptor(PcDescriptorsLayout::kRuntimeCall, 0, 0,
|
||||
TokenPosition(token_positions[i]), 0, 1);
|
||||
const TokenPosition& tp = TokenPosition::Deserialize(token_positions[i]);
|
||||
descriptors->AddDescriptor(PcDescriptorsLayout::kRuntimeCall, 0, 0, tp, 0,
|
||||
1);
|
||||
}
|
||||
|
||||
const PcDescriptors& finalized_descriptors =
|
||||
@@ -158,11 +158,12 @@ ISOLATE_UNIT_TEST_CASE(DescriptorList_TokenPositions) {
|
||||
|
||||
intptr_t i = 0;
|
||||
while (it.MoveNext()) {
|
||||
if (token_positions[i] != it.TokenPos().value()) {
|
||||
OS::PrintErr("[%" Pd "]: Expected: %" Pd " != %" Pd "\n", i,
|
||||
token_positions[i], it.TokenPos().value());
|
||||
const TokenPosition& tp = TokenPosition::Deserialize(token_positions[i]);
|
||||
if (tp != it.TokenPos()) {
|
||||
OS::PrintErr("[%" Pd "]: Expected: %s != %s\n", i, tp.ToCString(),
|
||||
it.TokenPos().ToCString());
|
||||
}
|
||||
EXPECT(token_positions[i] == it.TokenPos().value());
|
||||
EXPECT(tp == it.TokenPos());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,7 +516,7 @@ void TypeFeedbackSaver::VisitFunction(const Function& function) {
|
||||
WriteString(str_);
|
||||
|
||||
WriteInt(function.kind());
|
||||
WriteInt(function.token_pos().value());
|
||||
WriteInt(function.token_pos().Serialize());
|
||||
|
||||
code_ = function.CurrentCode();
|
||||
intptr_t usage = function.usage_counter();
|
||||
@@ -814,7 +814,7 @@ ObjectPtr TypeFeedbackLoader::LoadFunction() {
|
||||
|
||||
func_name_ = ReadString(); // Without private mangling.
|
||||
FunctionLayout::Kind kind = static_cast<FunctionLayout::Kind>(ReadInt());
|
||||
intptr_t token_pos = ReadInt();
|
||||
const TokenPosition& token_pos = TokenPosition::Deserialize(ReadInt());
|
||||
intptr_t usage = ReadInt();
|
||||
intptr_t inlining_depth = ReadInt();
|
||||
intptr_t num_call_sites = ReadInt();
|
||||
@@ -926,7 +926,7 @@ ObjectPtr TypeFeedbackLoader::LoadFunction() {
|
||||
}
|
||||
|
||||
FunctionPtr TypeFeedbackLoader::FindFunction(FunctionLayout::Kind kind,
|
||||
intptr_t token_pos) {
|
||||
const TokenPosition& token_pos) {
|
||||
if (cls_name_.Equals(Symbols::TopLevel())) {
|
||||
func_ = lib_.LookupFunctionAllowPrivate(func_name_);
|
||||
} else {
|
||||
@@ -969,8 +969,7 @@ FunctionPtr TypeFeedbackLoader::FindFunction(FunctionLayout::Kind kind,
|
||||
bool found = false;
|
||||
for (intptr_t i = 0; i < closure_functions.Length(); i++) {
|
||||
func_ ^= closure_functions.At(i);
|
||||
if ((func_.Owner() == cls_.raw()) &&
|
||||
(func_.token_pos().value() == token_pos)) {
|
||||
if (func_.Owner() == cls_.raw() && func_.token_pos() == token_pos) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -102,7 +102,8 @@ class TypeFeedbackLoader : public ValueObject {
|
||||
ObjectPtr LoadClasses();
|
||||
ObjectPtr LoadFields();
|
||||
ObjectPtr LoadFunction();
|
||||
FunctionPtr FindFunction(FunctionLayout::Kind kind, intptr_t token_pos);
|
||||
FunctionPtr FindFunction(FunctionLayout::Kind kind,
|
||||
const TokenPosition& token_pos);
|
||||
|
||||
ClassPtr ReadClassByName();
|
||||
StringPtr ReadString();
|
||||
|
||||
@@ -94,7 +94,7 @@ class FieldKeyValueTrait {
|
||||
static inline intptr_t Hashcode(Key key) {
|
||||
const TokenPosition token_pos = key->token_pos();
|
||||
if (token_pos.IsReal()) {
|
||||
return token_pos.value();
|
||||
return token_pos.Hash();
|
||||
}
|
||||
return key->kernel_offset();
|
||||
}
|
||||
@@ -117,7 +117,7 @@ class ClassKeyValueTrait {
|
||||
|
||||
static Value ValueOf(Pair kv) { return kv; }
|
||||
|
||||
static inline intptr_t Hashcode(Key key) { return key->token_pos().value(); }
|
||||
static inline intptr_t Hashcode(Key key) { return key->token_pos().Hash(); }
|
||||
|
||||
static inline bool IsKeyEqual(Pair pair, Key key) {
|
||||
return pair->raw() == key->raw();
|
||||
|
||||
@@ -339,7 +339,8 @@ void Disassembler::DisassembleCodeHelper(const char* function_fullname,
|
||||
THR_Print("%s}\n", handlers.ToCString());
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
|
||||
if (code.catch_entry_moves_maps() != Object::null()) {
|
||||
if (FLAG_precompiled_mode &&
|
||||
code.catch_entry_moves_maps() != Object::null()) {
|
||||
THR_Print("Catch entry moves for function '%s' {\n", function_fullname);
|
||||
CatchEntryMovesMapReader reader(
|
||||
TypedData::Handle(code.catch_entry_moves_maps()));
|
||||
|
||||
@@ -768,7 +768,7 @@ Instruction* FlowGraphDeserializer::ParseInstruction(SExpList* list) {
|
||||
TokenPosition token_pos = TokenPosition::kNoSource;
|
||||
if (auto const token_int =
|
||||
CheckInteger(list->ExtraLookupValue("token_pos"))) {
|
||||
token_pos = TokenPosition(token_int->value());
|
||||
token_pos = TokenPosition::Deserialize(token_int->value());
|
||||
}
|
||||
InstrInfo common_info = {deopt_id, token_pos};
|
||||
|
||||
@@ -1833,7 +1833,7 @@ bool FlowGraphDeserializer::ParseType(SExpression* sexp, Object* out) {
|
||||
}
|
||||
TokenPosition token_pos = TokenPosition::kNoSource;
|
||||
if (const auto pos_sexp = CheckInteger(list->ExtraLookupValue("token_pos"))) {
|
||||
token_pos = TokenPosition(pos_sexp->value());
|
||||
token_pos = TokenPosition::Deserialize(pos_sexp->value());
|
||||
}
|
||||
auto type_args_ptr = &Object::null_type_arguments();
|
||||
if (const auto ta_sexp = list->ExtraLookupValue("type_args")) {
|
||||
|
||||
@@ -437,7 +437,7 @@ SExpression* FlowGraphSerializer::AbstractTypeToSExp(const AbstractType& t) {
|
||||
AddSymbol(sexp, "Type");
|
||||
const auto& type = Type::Cast(t);
|
||||
if (!type.token_pos().IsNoSource()) {
|
||||
AddExtraInteger(sexp, "token_pos", type.token_pos().value());
|
||||
AddExtraInteger(sexp, "token_pos", type.token_pos().Serialize());
|
||||
}
|
||||
// We want to check for the type being recursive before we may serialize
|
||||
// any sub-parts that include possible TypeRefs to this type.
|
||||
@@ -823,7 +823,7 @@ void Instruction::AddExtraInfoToSExpression(SExpList* sexp,
|
||||
sexp->AddExtra("env", env()->ToSExpression(s));
|
||||
}
|
||||
if (!token_pos().IsNoSource()) {
|
||||
s->AddExtraInteger(sexp, "token_pos", token_pos().value());
|
||||
s->AddExtraInteger(sexp, "token_pos", token_pos().Serialize());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1692,9 +1692,7 @@ class LoadOptimizer : public ValueObject {
|
||||
|
||||
// For now, bail out for large functions to avoid OOM situations.
|
||||
// TODO(fschneider): Fix the memory consumption issue.
|
||||
intptr_t function_length = graph->function().end_token_pos().Pos() -
|
||||
graph->function().token_pos().Pos();
|
||||
if (function_length >= FLAG_huge_method_cutoff_in_tokens) {
|
||||
if (graph->function().SourceSize() >= FLAG_huge_method_cutoff_in_tokens) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2850,9 +2848,7 @@ class StoreOptimizer : public LivenessAnalysis {
|
||||
|
||||
// For now, bail out for large functions to avoid OOM situations.
|
||||
// TODO(fschneider): Fix the memory consumption issue.
|
||||
intptr_t function_length = graph->function().end_token_pos().Pos() -
|
||||
graph->function().token_pos().Pos();
|
||||
if (function_length >= FLAG_huge_method_cutoff_in_tokens) {
|
||||
if (graph->function().SourceSize() >= FLAG_huge_method_cutoff_in_tokens) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -103,11 +103,11 @@ void RunTestInMode(CompilerPass::PipelineMode mode) {
|
||||
EXPECT_EQ(3, yield_points.length());
|
||||
|
||||
EXPECT_EQ(1, yield_points[0].first);
|
||||
EXPECT_EQ(88, yield_points[0].second.value());
|
||||
EXPECT_EQ(88, yield_points[0].second.Pos());
|
||||
EXPECT_EQ(2, yield_points[1].first);
|
||||
EXPECT_EQ(129, yield_points[1].second.value());
|
||||
EXPECT_EQ(129, yield_points[1].second.Pos());
|
||||
EXPECT_EQ(3, yield_points[2].first);
|
||||
EXPECT_EQ(170, yield_points[2].second.value());
|
||||
EXPECT_EQ(170, yield_points[2].second.Pos());
|
||||
};
|
||||
|
||||
validate_indices(*GetYieldPointsFromGraph(flow_graph));
|
||||
|
||||
@@ -4839,8 +4839,9 @@ Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration() {
|
||||
|
||||
// Use position of equal sign if it exists. If the equal sign does not exist
|
||||
// use the position of the identifier.
|
||||
TokenPosition debug_position =
|
||||
Utils::Maximum(helper.position_, helper.equals_position_);
|
||||
const TokenPosition debug_position = helper.equals_position_.IsReal()
|
||||
? helper.equals_position_
|
||||
: helper.position_;
|
||||
if (NeedsDebugStepCheck(stack(), debug_position)) {
|
||||
instructions = DebugStepCheck(debug_position) + instructions;
|
||||
}
|
||||
@@ -4882,7 +4883,7 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionNode(
|
||||
// Positions has to be unique in regards to the parent.
|
||||
// A non-real at this point is probably -1, we cannot blindly use that
|
||||
// as others might use it too. Create a new dummy non-real TokenPosition.
|
||||
position = TokenPosition(offset).ToSynthetic();
|
||||
position = TokenPosition::Synthetic(offset);
|
||||
}
|
||||
|
||||
// The VM has a per-isolate table of functions indexed by the enclosing
|
||||
|
||||
@@ -296,8 +296,8 @@ class FunctionNodeHelper {
|
||||
void SetNext(Field field) { next_read_ = field; }
|
||||
void SetJustRead(Field field) { next_read_ = field + 1; }
|
||||
|
||||
TokenPosition position_;
|
||||
TokenPosition end_position_;
|
||||
TokenPosition position_ = TokenPosition::kNoSource;
|
||||
TokenPosition end_position_ = TokenPosition::kNoSource;
|
||||
AsyncMarker async_marker_;
|
||||
AsyncMarker dart_async_marker_;
|
||||
intptr_t total_parameter_count_ = 0;
|
||||
@@ -352,7 +352,7 @@ class TypeParameterHelper {
|
||||
return (flags_ & kIsGenericCovariantImpl) != 0;
|
||||
}
|
||||
|
||||
TokenPosition position_;
|
||||
TokenPosition position_ = TokenPosition::kNoSource;
|
||||
uint8_t flags_ = 0;
|
||||
StringIndex name_index_;
|
||||
|
||||
@@ -415,8 +415,8 @@ class VariableDeclarationHelper {
|
||||
return (flags_ & kIsGenericCovariantImpl) != 0;
|
||||
}
|
||||
|
||||
TokenPosition position_;
|
||||
TokenPosition equals_position_;
|
||||
TokenPosition position_ = TokenPosition::kNoSource;
|
||||
TokenPosition equals_position_ = TokenPosition::kNoSource;
|
||||
uint8_t flags_ = 0;
|
||||
StringIndex name_index_;
|
||||
intptr_t annotation_count_ = 0;
|
||||
@@ -488,8 +488,8 @@ class FieldHelper {
|
||||
|
||||
NameIndex canonical_name_getter_;
|
||||
NameIndex canonical_name_setter_;
|
||||
TokenPosition position_;
|
||||
TokenPosition end_position_;
|
||||
TokenPosition position_ = TokenPosition::kNoSource;
|
||||
TokenPosition end_position_ = TokenPosition::kNoSource;
|
||||
uint32_t flags_ = 0;
|
||||
intptr_t source_uri_index_ = 0;
|
||||
intptr_t annotation_count_ = 0;
|
||||
@@ -589,9 +589,9 @@ class ProcedureHelper {
|
||||
}
|
||||
|
||||
NameIndex canonical_name_;
|
||||
TokenPosition start_position_;
|
||||
TokenPosition position_;
|
||||
TokenPosition end_position_;
|
||||
TokenPosition start_position_ = TokenPosition::kNoSource;
|
||||
TokenPosition position_ = TokenPosition::kNoSource;
|
||||
TokenPosition end_position_ = TokenPosition::kNoSource;
|
||||
Kind kind_;
|
||||
uint32_t flags_ = 0;
|
||||
intptr_t source_uri_index_ = 0;
|
||||
@@ -655,9 +655,9 @@ class ConstructorHelper {
|
||||
bool IsSynthetic() { return (flags_ & kSynthetic) != 0; }
|
||||
|
||||
NameIndex canonical_name_;
|
||||
TokenPosition start_position_;
|
||||
TokenPosition position_;
|
||||
TokenPosition end_position_;
|
||||
TokenPosition start_position_ = TokenPosition::kNoSource;
|
||||
TokenPosition position_ = TokenPosition::kNoSource;
|
||||
TokenPosition end_position_ = TokenPosition::kNoSource;
|
||||
uint8_t flags_ = 0;
|
||||
intptr_t source_uri_index_ = 0;
|
||||
intptr_t annotation_count_ = 0;
|
||||
@@ -733,9 +733,9 @@ class ClassHelper {
|
||||
}
|
||||
|
||||
NameIndex canonical_name_;
|
||||
TokenPosition start_position_;
|
||||
TokenPosition position_;
|
||||
TokenPosition end_position_;
|
||||
TokenPosition start_position_ = TokenPosition::kNoSource;
|
||||
TokenPosition position_ = TokenPosition::kNoSource;
|
||||
TokenPosition end_position_ = TokenPosition::kNoSource;
|
||||
StringIndex name_index_;
|
||||
intptr_t source_uri_index_ = 0;
|
||||
intptr_t annotation_count_ = 0;
|
||||
|
||||
@@ -162,7 +162,7 @@ class ScopeBuilder {
|
||||
intptr_t name_index_;
|
||||
|
||||
bool needs_expr_temp_;
|
||||
TokenPosition first_body_token_position_;
|
||||
TokenPosition first_body_token_position_ = TokenPosition::kNoSource;
|
||||
|
||||
KernelReaderHelper helper_;
|
||||
ConstantReader constant_reader_;
|
||||
|
||||
@@ -724,8 +724,7 @@ static ObjectPtr CompileFunctionHelper(CompilationPipeline* pipeline,
|
||||
ParsedFunction* parsed_function = new (zone)
|
||||
ParsedFunction(thread, Function::ZoneHandle(zone, function.raw()));
|
||||
if (trace_compiler) {
|
||||
const intptr_t token_size =
|
||||
function.end_token_pos().Pos() - function.token_pos().Pos();
|
||||
const intptr_t token_size = function.SourceSize();
|
||||
THR_Print("Compiling %s%sfunction %s: '%s' @ token %s, size %" Pd "\n",
|
||||
(osr_id == Compiler::kNoOSRDeoptId ? "" : "osr "),
|
||||
(optimized ? "optimized " : ""),
|
||||
@@ -1300,9 +1299,9 @@ CompilationPipeline* CompilationPipeline::New(Zone* zone,
|
||||
|
||||
DEFINE_RUNTIME_ENTRY(CompileFunction, 1) {
|
||||
const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
|
||||
FATAL3("Precompilation missed function %s (%" Pd ", %s)\n",
|
||||
FATAL3("Precompilation missed function %s (%s, %s)\n",
|
||||
function.ToLibNamePrefixedQualifiedCString(),
|
||||
function.token_pos().value(),
|
||||
function.token_pos().ToCString(),
|
||||
Function::KindToCString(function.kind()));
|
||||
}
|
||||
|
||||
|
||||
+136
-132
@@ -109,8 +109,7 @@ void BreakpointLocation::SetResolved(const Function& func,
|
||||
TokenPosition token_pos) {
|
||||
ASSERT(!IsLatent());
|
||||
ASSERT(func.script() == script_);
|
||||
ASSERT((func.token_pos() <= token_pos) &&
|
||||
(token_pos <= func.end_token_pos()));
|
||||
ASSERT(token_pos.IsWithin(func.token_pos(), func.end_token_pos()));
|
||||
ASSERT(func.is_debuggable());
|
||||
function_ = func.raw();
|
||||
token_pos_ = token_pos;
|
||||
@@ -394,11 +393,10 @@ static bool FunctionOverlaps(const Function& func,
|
||||
const Script& script,
|
||||
TokenPosition token_pos,
|
||||
TokenPosition end_token_pos) {
|
||||
TokenPosition func_start = func.token_pos();
|
||||
if (((func_start <= token_pos) && (token_pos <= func.end_token_pos())) ||
|
||||
((token_pos <= func_start) && (func_start <= end_token_pos))) {
|
||||
// Check script equality second because it allocates
|
||||
// handles as a side effect.
|
||||
const TokenPosition& func_start = func.token_pos();
|
||||
if (token_pos.IsWithin(func_start, func.end_token_pos()) ||
|
||||
func_start.IsWithin(token_pos, end_token_pos)) {
|
||||
// Check script equality last because it allocates handles as a side effect.
|
||||
return func.script() == script.raw();
|
||||
}
|
||||
return false;
|
||||
@@ -566,24 +564,20 @@ intptr_t ActivationFrame::DeoptId() {
|
||||
|
||||
intptr_t ActivationFrame::LineNumber() {
|
||||
// Compute line number lazily since it causes scanning of the script.
|
||||
if ((line_number_ < 0) && TokenPos().IsSourcePosition()) {
|
||||
const TokenPosition token_pos = TokenPos().SourcePosition();
|
||||
const TokenPosition& token_pos = TokenPos();
|
||||
if ((line_number_ < 0) && token_pos.IsReal()) {
|
||||
const Script& script = Script::Handle(SourceScript());
|
||||
script.GetTokenLocation(token_pos, &line_number_, NULL);
|
||||
script.GetTokenLocation(token_pos, &line_number_, nullptr);
|
||||
}
|
||||
return line_number_;
|
||||
}
|
||||
|
||||
intptr_t ActivationFrame::ColumnNumber() {
|
||||
// Compute column number lazily since it causes scanning of the script.
|
||||
if ((column_number_ < 0) && TokenPos().IsSourcePosition()) {
|
||||
const TokenPosition token_pos = TokenPos().SourcePosition();
|
||||
const TokenPosition& token_pos = TokenPos();
|
||||
if ((column_number_ < 0) && token_pos.IsReal()) {
|
||||
const Script& script = Script::Handle(SourceScript());
|
||||
if (script.HasSource()) {
|
||||
script.GetTokenLocation(token_pos, &line_number_, &column_number_);
|
||||
} else {
|
||||
column_number_ = -1;
|
||||
}
|
||||
script.GetTokenLocation(token_pos, &line_number_, &column_number_);
|
||||
}
|
||||
return column_number_;
|
||||
}
|
||||
@@ -648,13 +642,14 @@ intptr_t ActivationFrame::ContextLevel() {
|
||||
}
|
||||
intptr_t var_desc_len = var_descriptors_.Length();
|
||||
bool found = false;
|
||||
// We store the deopt ids as real token positions.
|
||||
const auto to_compare = TokenPosition::Deserialize(deopt_id);
|
||||
for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
|
||||
LocalVarDescriptorsLayout::VarInfo var_info;
|
||||
var_descriptors_.GetInfo(cur_idx, &var_info);
|
||||
const int8_t kind = var_info.kind();
|
||||
if ((kind == LocalVarDescriptorsLayout::kContextLevel) &&
|
||||
(deopt_id >= var_info.begin_pos.value()) &&
|
||||
(deopt_id <= var_info.end_pos.value())) {
|
||||
to_compare.IsWithin(var_info.begin_pos, var_info.end_pos)) {
|
||||
context_level_ = var_info.index();
|
||||
found = true;
|
||||
break;
|
||||
@@ -925,51 +920,51 @@ void ActivationFrame::GetDescIndices() {
|
||||
(kind != LocalVarDescriptorsLayout::kContextVar)) {
|
||||
continue;
|
||||
}
|
||||
if ((var_info.begin_pos <= activation_token_pos) &&
|
||||
(activation_token_pos <= var_info.end_pos)) {
|
||||
if ((kind == LocalVarDescriptorsLayout::kContextVar) &&
|
||||
(ContextLevel() < var_info.scope_id)) {
|
||||
// The variable is textually in scope but the context level
|
||||
// at the activation frame's PC is lower than the context
|
||||
// level of the variable. The context containing the variable
|
||||
// has already been removed from the chain. This can happen when we
|
||||
// break at a return statement, since the contexts get discarded
|
||||
// before the debugger gets called.
|
||||
continue;
|
||||
}
|
||||
// The current variable is textually in scope. Now check whether
|
||||
// there is another local variable with the same name that shadows
|
||||
// or is shadowed by this variable.
|
||||
String& var_name = String::Handle(var_descriptors_.GetName(cur_idx));
|
||||
intptr_t indices_len = desc_indices_.length();
|
||||
bool name_match_found = false;
|
||||
for (intptr_t i = 0; i < indices_len; i++) {
|
||||
if (var_name.Equals(*var_names[i])) {
|
||||
// Found two local variables with the same name. Now determine
|
||||
// which one is shadowed.
|
||||
name_match_found = true;
|
||||
LocalVarDescriptorsLayout::VarInfo i_var_info;
|
||||
var_descriptors_.GetInfo(desc_indices_[i], &i_var_info);
|
||||
if (i_var_info.begin_pos < var_info.begin_pos) {
|
||||
// The variable we found earlier is in an outer scope
|
||||
// and is shadowed by the current variable. Replace the
|
||||
// descriptor index of the previously found variable
|
||||
// with the descriptor index of the current variable.
|
||||
desc_indices_[i] = cur_idx;
|
||||
} else {
|
||||
// The variable we found earlier is in an inner scope
|
||||
// and shadows the current variable. Skip the current
|
||||
// variable. (Nothing to do.)
|
||||
}
|
||||
break; // Stop looking for name matches.
|
||||
if (!activation_token_pos.IsWithin(var_info.begin_pos, var_info.end_pos)) {
|
||||
continue;
|
||||
}
|
||||
if ((kind == LocalVarDescriptorsLayout::kContextVar) &&
|
||||
(ContextLevel() < var_info.scope_id)) {
|
||||
// The variable is textually in scope but the context level
|
||||
// at the activation frame's PC is lower than the context
|
||||
// level of the variable. The context containing the variable
|
||||
// has already been removed from the chain. This can happen when we
|
||||
// break at a return statement, since the contexts get discarded
|
||||
// before the debugger gets called.
|
||||
continue;
|
||||
}
|
||||
// The current variable is textually in scope. Now check whether
|
||||
// there is another local variable with the same name that shadows
|
||||
// or is shadowed by this variable.
|
||||
String& var_name = String::Handle(var_descriptors_.GetName(cur_idx));
|
||||
intptr_t indices_len = desc_indices_.length();
|
||||
bool name_match_found = false;
|
||||
for (intptr_t i = 0; i < indices_len; i++) {
|
||||
if (var_name.Equals(*var_names[i])) {
|
||||
// Found two local variables with the same name. Now determine
|
||||
// which one is shadowed.
|
||||
name_match_found = true;
|
||||
LocalVarDescriptorsLayout::VarInfo i_var_info;
|
||||
var_descriptors_.GetInfo(desc_indices_[i], &i_var_info);
|
||||
if (i_var_info.begin_pos < var_info.begin_pos) {
|
||||
// The variable we found earlier is in an outer scope
|
||||
// and is shadowed by the current variable. Replace the
|
||||
// descriptor index of the previously found variable
|
||||
// with the descriptor index of the current variable.
|
||||
desc_indices_[i] = cur_idx;
|
||||
} else {
|
||||
// The variable we found earlier is in an inner scope
|
||||
// and shadows the current variable. Skip the current
|
||||
// variable. (Nothing to do.)
|
||||
}
|
||||
break; // Stop looking for name matches.
|
||||
}
|
||||
if (!name_match_found) {
|
||||
// No duplicate name found. Add the current descriptor index to the
|
||||
// list of visible variables.
|
||||
desc_indices_.Add(cur_idx);
|
||||
var_names.Add(&var_name);
|
||||
}
|
||||
}
|
||||
if (!name_match_found) {
|
||||
// No duplicate name found. Add the current descriptor index to the
|
||||
// list of visible variables.
|
||||
desc_indices_.Add(cur_idx);
|
||||
var_names.Add(&var_name);
|
||||
}
|
||||
}
|
||||
vars_initialized_ = true;
|
||||
@@ -1167,7 +1162,7 @@ ArrayPtr ActivationFrame::GetLocalVariables() {
|
||||
Object& value = Instance::Handle();
|
||||
const Array& list = Array::Handle(Array::New(2 * num_variables));
|
||||
for (intptr_t i = 0; i < num_variables; i++) {
|
||||
TokenPosition ignore;
|
||||
TokenPosition ignore = TokenPosition::kNoSource;
|
||||
VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value);
|
||||
list.SetAt(2 * i, var_name);
|
||||
list.SetAt((2 * i) + 1, value);
|
||||
@@ -1181,7 +1176,7 @@ ObjectPtr ActivationFrame::GetReceiver() {
|
||||
String& var_name = String::Handle();
|
||||
Instance& value = Instance::Handle();
|
||||
for (intptr_t i = 0; i < num_variables; i++) {
|
||||
TokenPosition ignore;
|
||||
TokenPosition ignore = TokenPosition::kNoSource;
|
||||
VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value);
|
||||
if (var_name.Equals(Symbols::This())) {
|
||||
return value.raw();
|
||||
@@ -1232,7 +1227,7 @@ TypeArgumentsPtr ActivationFrame::BuildParameters(
|
||||
TypeArguments& type_arguments = TypeArguments::Handle();
|
||||
intptr_t num_variables = desc_indices_.length();
|
||||
for (intptr_t i = 0; i < num_variables; i++) {
|
||||
TokenPosition ignore;
|
||||
TokenPosition ignore = TokenPosition::kNoSource;
|
||||
VariableAt(i, &name, &ignore, &ignore, &ignore, &value);
|
||||
if (name.Equals(Symbols::FunctionTypeArgumentsVar())) {
|
||||
type_arguments_available = true;
|
||||
@@ -1347,7 +1342,7 @@ void ActivationFrame::PrintToJSONObjectRegular(JSONObject* jsobj) {
|
||||
const Script& script = Script::Handle(SourceScript());
|
||||
jsobj->AddProperty("type", "Frame");
|
||||
jsobj->AddProperty("kind", KindToCString(kind_));
|
||||
const TokenPosition pos = TokenPos().SourcePosition();
|
||||
const TokenPosition& pos = TokenPos();
|
||||
jsobj->AddLocation(script, pos);
|
||||
jsobj->AddProperty("function", function());
|
||||
jsobj->AddProperty("code", code());
|
||||
@@ -1357,9 +1352,9 @@ void ActivationFrame::PrintToJSONObjectRegular(JSONObject* jsobj) {
|
||||
for (intptr_t v = 0; v < num_vars; v++) {
|
||||
String& var_name = String::Handle();
|
||||
Instance& var_value = Instance::Handle();
|
||||
TokenPosition declaration_token_pos;
|
||||
TokenPosition visible_start_token_pos;
|
||||
TokenPosition visible_end_token_pos;
|
||||
TokenPosition declaration_token_pos = TokenPosition::kNoSource;
|
||||
TokenPosition visible_start_token_pos = TokenPosition::kNoSource;
|
||||
TokenPosition visible_end_token_pos = TokenPosition::kNoSource;
|
||||
VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos,
|
||||
&visible_end_token_pos, &var_value);
|
||||
if (!IsSyntheticVariableName(var_name)) {
|
||||
@@ -1383,7 +1378,7 @@ void ActivationFrame::PrintToJSONObjectAsyncCausal(JSONObject* jsobj) {
|
||||
jsobj->AddProperty("type", "Frame");
|
||||
jsobj->AddProperty("kind", KindToCString(kind_));
|
||||
const Script& script = Script::Handle(SourceScript());
|
||||
const TokenPosition pos = TokenPos().SourcePosition();
|
||||
const TokenPosition& pos = TokenPos();
|
||||
jsobj->AddLocation(script, pos);
|
||||
jsobj->AddProperty("function", function());
|
||||
jsobj->AddProperty("code", code());
|
||||
@@ -2239,16 +2234,14 @@ static void RefineBreakpointPos(const Script& script,
|
||||
intptr_t token_start_column = -1;
|
||||
intptr_t token_line = -1;
|
||||
if (requested_column >= 0) {
|
||||
TokenPosition ignored;
|
||||
TokenPosition end_of_line_pos;
|
||||
TokenPosition ignored = TokenPosition::kNoSource;
|
||||
TokenPosition end_of_line_pos = TokenPosition::kNoSource;
|
||||
script.GetTokenLocation(pos, &token_line, &token_start_column);
|
||||
script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
|
||||
TokenPosition token_end_pos =
|
||||
(end_of_line_pos < next_closest_token_position)
|
||||
? end_of_line_pos
|
||||
: next_closest_token_position;
|
||||
TokenPosition::Min(next_closest_token_position, end_of_line_pos);
|
||||
|
||||
if ((token_end_pos < exact_token_pos) ||
|
||||
if ((exact_token_pos.IsReal() && (token_end_pos < exact_token_pos)) ||
|
||||
(token_start_column > *best_column)) {
|
||||
// Prefer the token with the lowest column number compatible
|
||||
// with the requested column.
|
||||
@@ -2261,9 +2254,11 @@ static void RefineBreakpointPos(const Script& script,
|
||||
*best_fit_pos = pos;
|
||||
*best_line = token_line;
|
||||
*best_column = token_start_column;
|
||||
// best_token_pos is only used when column number is specified.
|
||||
*best_token_pos = TokenPosition(exact_token_pos.value() -
|
||||
(requested_column - *best_column));
|
||||
// best_token_pos should only be real when the column number is specified.
|
||||
if (requested_column >= 0 && exact_token_pos.IsReal()) {
|
||||
*best_token_pos = TokenPosition::Deserialize(
|
||||
exact_token_pos.Pos() - (requested_column - *best_column));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2330,12 +2325,9 @@ TokenPosition Debugger::ResolveBreakpointPos(const Function& func,
|
||||
TokenPosition exact_token_pos) {
|
||||
ASSERT(!func.HasOptimizedCode());
|
||||
|
||||
if (requested_token_pos < func.token_pos()) {
|
||||
requested_token_pos = func.token_pos();
|
||||
}
|
||||
if (last_token_pos > func.end_token_pos()) {
|
||||
last_token_pos = func.end_token_pos();
|
||||
}
|
||||
requested_token_pos =
|
||||
TokenPosition::Max(requested_token_pos, func.token_pos());
|
||||
last_token_pos = TokenPosition::Min(last_token_pos, func.end_token_pos());
|
||||
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
Script& script = Script::Handle(zone, func.script());
|
||||
@@ -2351,15 +2343,19 @@ TokenPosition Debugger::ResolveBreakpointPos(const Function& func,
|
||||
TokenPosition best_fit_pos = TokenPosition::kMaxSource;
|
||||
intptr_t best_column = INT_MAX;
|
||||
intptr_t best_line = INT_MAX;
|
||||
// best_token_pos and exact_token_pos are only used
|
||||
// if column number is provided.
|
||||
// best_token_pos is only set to a real position if a real exact_token_pos
|
||||
// and a column number are provided.
|
||||
TokenPosition best_token_pos = TokenPosition::kNoSource;
|
||||
|
||||
PcDescriptors::Iterator iter(desc, kSafepointKind);
|
||||
while (iter.MoveNext()) {
|
||||
const TokenPosition pos = iter.TokenPos();
|
||||
if ((!pos.IsReal()) || (pos < requested_token_pos) ||
|
||||
(pos > last_token_pos)) {
|
||||
const TokenPosition& pos = iter.TokenPos();
|
||||
if (pos.IsSynthetic() && pos == requested_token_pos) {
|
||||
// if there's a safepoint for a synthetic function start and the start
|
||||
// was requested, we're done.
|
||||
return pos;
|
||||
}
|
||||
if (!pos.IsWithin(requested_token_pos, last_token_pos)) {
|
||||
// Token is not in the target range.
|
||||
continue;
|
||||
}
|
||||
@@ -2368,8 +2364,9 @@ TokenPosition Debugger::ResolveBreakpointPos(const Function& func,
|
||||
// Find next closest safepoint
|
||||
PcDescriptors::Iterator iter2(desc, kSafepointKind);
|
||||
while (iter2.MoveNext()) {
|
||||
const TokenPosition next = iter2.TokenPos();
|
||||
if (next < next_closest_token_position && next > pos) {
|
||||
const TokenPosition& next = iter2.TokenPos();
|
||||
if (!next.IsReal()) continue;
|
||||
if ((pos < next) && (next < next_closest_token_position)) {
|
||||
next_closest_token_position = next;
|
||||
}
|
||||
}
|
||||
@@ -2384,33 +2381,31 @@ TokenPosition Debugger::ResolveBreakpointPos(const Function& func,
|
||||
// the token on the line which is at the best fit column (if column
|
||||
// was specified) and has the lowest code address.
|
||||
if (best_fit_pos != TokenPosition::kMaxSource) {
|
||||
ASSERT(best_fit_pos.IsReal());
|
||||
const Script& script = Script::Handle(zone, func.script());
|
||||
const TokenPosition begin_pos = best_fit_pos;
|
||||
|
||||
TokenPosition end_of_line_pos;
|
||||
TokenPosition end_of_line_pos = TokenPosition::kNoSource;
|
||||
if (best_line == -1) {
|
||||
script.GetTokenLocation(begin_pos, &best_line, NULL);
|
||||
script.GetTokenLocation(begin_pos, &best_line, nullptr);
|
||||
}
|
||||
ASSERT(best_line > 0);
|
||||
TokenPosition ignored;
|
||||
TokenPosition ignored = TokenPosition::kNoSource;
|
||||
script.TokenRangeAtLine(best_line, &ignored, &end_of_line_pos);
|
||||
if (end_of_line_pos < begin_pos) {
|
||||
end_of_line_pos = begin_pos;
|
||||
}
|
||||
end_of_line_pos = TokenPosition::Max(end_of_line_pos, begin_pos);
|
||||
|
||||
uword lowest_pc_offset = kUwordMax;
|
||||
PcDescriptors::Iterator iter(desc, kSafepointKind);
|
||||
while (iter.MoveNext()) {
|
||||
const TokenPosition pos = iter.TokenPos();
|
||||
if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
|
||||
// Token is not on same line as best fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (requested_column >= 0) {
|
||||
const TokenPosition& pos = iter.TokenPos();
|
||||
if (best_token_pos.IsReal()) {
|
||||
if (pos != best_token_pos) {
|
||||
// Not an match for the requested column.
|
||||
continue;
|
||||
}
|
||||
} else if (!pos.IsWithin(begin_pos, end_of_line_pos)) {
|
||||
// Token is not on same line as best fit.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prefer the lowest pc offset.
|
||||
@@ -2557,14 +2552,14 @@ void Debugger::FindCompiledFunctions(
|
||||
}
|
||||
}
|
||||
|
||||
static void SelectBestFit(Function* best_fit, Function* func) {
|
||||
static void UpdateBestFit(Function* best_fit, const Function& func) {
|
||||
if (best_fit->IsNull()) {
|
||||
*best_fit = func->raw();
|
||||
} else {
|
||||
if ((func->token_pos() > best_fit->token_pos()) &&
|
||||
((func->end_token_pos() <= best_fit->end_token_pos()))) {
|
||||
*best_fit = func->raw();
|
||||
}
|
||||
*best_fit = func.raw();
|
||||
} else if ((best_fit->token_pos().IsSynthetic() ||
|
||||
func.token_pos().IsSynthetic() ||
|
||||
(best_fit->token_pos() < func.token_pos())) &&
|
||||
(func.end_token_pos() <= best_fit->end_token_pos())) {
|
||||
*best_fit = func.raw();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2623,7 +2618,7 @@ bool Debugger::FindBestFit(const Script& script,
|
||||
function ^= closures.At(i);
|
||||
if (FunctionOverlaps(function, script, token_pos, last_token_pos)) {
|
||||
// Select the inner most closure.
|
||||
SelectBestFit(best_fit, &function);
|
||||
UpdateBestFit(best_fit, function);
|
||||
}
|
||||
}
|
||||
if (!best_fit->IsNull()) {
|
||||
@@ -2688,8 +2683,8 @@ bool Debugger::FindBestFit(const Script& script,
|
||||
if (!fields.IsNull()) {
|
||||
const intptr_t num_fields = fields.Length();
|
||||
for (intptr_t pos = 0; pos < num_fields; pos++) {
|
||||
TokenPosition start;
|
||||
TokenPosition end;
|
||||
TokenPosition start = TokenPosition::kNoSource;
|
||||
TokenPosition end = TokenPosition::kNoSource;
|
||||
field ^= fields.At(pos);
|
||||
ASSERT(!field.IsNull());
|
||||
if (field.Script() != script.raw()) {
|
||||
@@ -2702,8 +2697,8 @@ bool Debugger::FindBestFit(const Script& script,
|
||||
}
|
||||
start = field.token_pos();
|
||||
end = field.end_token_pos();
|
||||
if ((start <= token_pos && token_pos <= end) ||
|
||||
(token_pos <= start && start <= last_token_pos)) {
|
||||
if (token_pos.IsWithin(start, end) ||
|
||||
start.IsWithin(token_pos, last_token_pos)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2803,7 +2798,7 @@ BreakpointLocation* Debugger::SetBreakpoint(const Script& script,
|
||||
// have already been compiled. We can resolve the breakpoint now.
|
||||
// If requested_column is larger than zero, [token_pos, last_token_pos]
|
||||
// governs one single line of code.
|
||||
TokenPosition exact_token_pos = TokenPosition(-1);
|
||||
TokenPosition exact_token_pos = TokenPosition::kNoSource;
|
||||
if (token_pos != last_token_pos && requested_column >= 0) {
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
exact_token_pos =
|
||||
@@ -3010,7 +3005,8 @@ BreakpointLocation* Debugger::BreakpointLocationAtLineCol(
|
||||
}
|
||||
return latent_bpt;
|
||||
}
|
||||
TokenPosition first_token_idx, last_token_idx;
|
||||
TokenPosition first_token_idx = TokenPosition::kNoSource;
|
||||
TokenPosition last_token_idx = TokenPosition::kNoSource;
|
||||
script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx);
|
||||
if (!first_token_idx.IsReal()) {
|
||||
// Script does not contain the given line number.
|
||||
@@ -3825,6 +3821,8 @@ void Debugger::NotifyIsolateCreated() {
|
||||
// the given token position.
|
||||
FunctionPtr Debugger::FindInnermostClosure(const Function& function,
|
||||
TokenPosition token_pos) {
|
||||
ASSERT(function.end_token_pos().IsReal());
|
||||
const TokenPosition& func_start = function.token_pos();
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
const Script& outer_origin = Script::Handle(zone, function.script());
|
||||
const GrowableObjectArray& closures = GrowableObjectArray::Handle(
|
||||
@@ -3834,12 +3832,16 @@ FunctionPtr Debugger::FindInnermostClosure(const Function& function,
|
||||
Function& best_fit = Function::Handle(zone);
|
||||
for (intptr_t i = 0; i < num_closures; i++) {
|
||||
closure ^= closures.At(i);
|
||||
if ((function.token_pos() < closure.token_pos()) &&
|
||||
(closure.end_token_pos() < function.end_token_pos()) &&
|
||||
(closure.token_pos() <= token_pos) &&
|
||||
(token_pos <= closure.end_token_pos()) &&
|
||||
const TokenPosition& closure_start = closure.token_pos();
|
||||
const TokenPosition& closure_end = closure.end_token_pos();
|
||||
// We're only interested in closures that have real ending token positions.
|
||||
// The starting token position can be synthetic.
|
||||
if (closure_end.IsReal() && (function.end_token_pos() > closure_end) &&
|
||||
(!closure_start.IsReal() || !func_start.IsReal() ||
|
||||
(closure_start > func_start)) &&
|
||||
token_pos.IsWithin(closure_start, closure_end) &&
|
||||
(closure.script() == outer_origin.raw())) {
|
||||
SelectBestFit(&best_fit, &closure);
|
||||
UpdateBestFit(&best_fit, closure);
|
||||
}
|
||||
}
|
||||
return best_fit.raw();
|
||||
@@ -3851,13 +3853,14 @@ FunctionPtr Debugger::FindInnermostClosure(const Function& function,
|
||||
TokenPosition Debugger::FindExactTokenPosition(const Script& script,
|
||||
TokenPosition start_of_line,
|
||||
intptr_t column_number) {
|
||||
intptr_t line = -1;
|
||||
intptr_t col = -1;
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
kernel::KernelLineStartsReader line_starts_reader(
|
||||
TypedData::Handle(zone, script.line_starts()), zone);
|
||||
line_starts_reader.LocationForPosition(start_of_line.value(), &line, &col);
|
||||
return TokenPosition(start_of_line.value() + (column_number - col));
|
||||
intptr_t line;
|
||||
intptr_t col;
|
||||
script.GetTokenLocation(start_of_line, &line, &col);
|
||||
if (line < 0) {
|
||||
return TokenPosition::kNoSource;
|
||||
}
|
||||
return TokenPosition::Deserialize(start_of_line.Pos() +
|
||||
(column_number - col));
|
||||
}
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
@@ -3988,7 +3991,8 @@ void Debugger::NotifyDoneLoading() {
|
||||
intptr_t line_number = matched_loc->requested_line_number();
|
||||
intptr_t column_number = matched_loc->requested_column_number();
|
||||
ASSERT(line_number >= 0);
|
||||
TokenPosition first_token_pos, last_token_pos;
|
||||
TokenPosition first_token_pos = TokenPosition::kNoSource;
|
||||
TokenPosition last_token_pos = TokenPosition::kNoSource;
|
||||
script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
|
||||
if (!first_token_pos.IsDebugPause() || !last_token_pos.IsDebugPause()) {
|
||||
// Script does not contain the given line number or there are no
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ struct FunctionIndexPair {
|
||||
|
||||
static Value ValueOf(Pair kv) { return kv.index_; }
|
||||
|
||||
static inline intptr_t Hashcode(Key key) { return key->token_pos().value(); }
|
||||
static inline intptr_t Hashcode(Key key) { return key->token_pos().Hash(); }
|
||||
|
||||
static inline bool IsKeyEqual(Pair pair, Key key) {
|
||||
return pair.function_->raw() == key->raw();
|
||||
|
||||
@@ -320,7 +320,7 @@ void JSONStream::PrintValue(Breakpoint* bpt) {
|
||||
|
||||
void JSONStream::PrintValue(TokenPosition tp) {
|
||||
PrintCommaIfNeeded();
|
||||
PrintValue(tp.value());
|
||||
PrintValue(static_cast<intptr_t>(tp.Serialize()));
|
||||
}
|
||||
|
||||
void JSONStream::PrintValue(const ServiceEvent* event) {
|
||||
|
||||
@@ -78,11 +78,11 @@ void KernelLineStartsReader::TokenRangeAtLine(
|
||||
for (intptr_t i = 0; i < line_number; ++i) {
|
||||
cumulative += helper_->At(line_starts_data_, i);
|
||||
}
|
||||
*first_token_index = dart::TokenPosition(cumulative);
|
||||
*first_token_index = dart::TokenPosition::Deserialize(cumulative);
|
||||
if (line_number == line_starts_data_.Length()) {
|
||||
*last_token_index = dart::TokenPosition(source_length);
|
||||
*last_token_index = dart::TokenPosition::Deserialize(source_length);
|
||||
} else {
|
||||
*last_token_index = dart::TokenPosition(
|
||||
*last_token_index = dart::TokenPosition::Deserialize(
|
||||
cumulative + helper_->At(line_starts_data_, line_number) - 1);
|
||||
}
|
||||
}
|
||||
@@ -168,7 +168,7 @@ void KernelTokenPositionCollector::CollectTokenPositions(
|
||||
void KernelTokenPositionCollector::RecordTokenPosition(TokenPosition position) {
|
||||
if (record_for_script_id_ == current_script_id_ &&
|
||||
record_token_positions_into_ != NULL && position.IsReal()) {
|
||||
record_token_positions_into_->Add(position.value());
|
||||
record_token_positions_into_->Add(position.Serialize());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,8 +259,8 @@ void CollectTokenPositionsFor(const Script& interesting_script) {
|
||||
if (entry.IsClass()) {
|
||||
const Class& klass = Class::Cast(entry);
|
||||
if (klass.script() == interesting_script.raw()) {
|
||||
token_positions.Add(klass.token_pos().value());
|
||||
token_positions.Add(klass.end_token_pos().value());
|
||||
token_positions.Add(klass.token_pos().Serialize());
|
||||
token_positions.Add(klass.end_token_pos().Serialize());
|
||||
}
|
||||
if (klass.is_finalized()) {
|
||||
temp_array = klass.fields();
|
||||
|
||||
+11
-16
@@ -229,14 +229,18 @@ class Reader : public ValueObject {
|
||||
raw_buffer_(buffer),
|
||||
typed_data_(NULL),
|
||||
size_(size),
|
||||
offset_(0) {}
|
||||
offset_(0),
|
||||
max_position_(TokenPosition::kNoSource),
|
||||
min_position_(TokenPosition::kNoSource) {}
|
||||
|
||||
explicit Reader(const ExternalTypedData& typed_data)
|
||||
: thread_(Thread::Current()),
|
||||
raw_buffer_(NULL),
|
||||
typed_data_(&typed_data),
|
||||
size_(typed_data.IsNull() ? 0 : typed_data.Length()),
|
||||
offset_(0) {}
|
||||
offset_(0),
|
||||
max_position_(TokenPosition::kNoSource),
|
||||
min_position_(TokenPosition::kNoSource) {}
|
||||
|
||||
uint32_t ReadFromIndex(intptr_t end_offset,
|
||||
intptr_t fields_before,
|
||||
@@ -329,14 +333,9 @@ class Reader : public ValueObject {
|
||||
// Position is saved as unsigned,
|
||||
// but actually ranges from -1 and up (thus the -1)
|
||||
intptr_t value = ReadUInt() - 1;
|
||||
TokenPosition result = TokenPosition(value);
|
||||
max_position_ = Utils::Maximum(max_position_, result);
|
||||
if (min_position_.IsNoSource()) {
|
||||
min_position_ = result;
|
||||
} else if (result.IsReal()) {
|
||||
min_position_ = Utils::Minimum(min_position_, result);
|
||||
}
|
||||
|
||||
TokenPosition result = TokenPosition::Deserialize(value);
|
||||
max_position_ = TokenPosition::Max(max_position_, result);
|
||||
min_position_ = TokenPosition::Min(min_position_, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -553,12 +552,8 @@ class PositionScope {
|
||||
}
|
||||
|
||||
~PositionScope() {
|
||||
if (reader_->min_position_.IsNoSource()) {
|
||||
reader_->min_position_ = min_;
|
||||
} else if (min_.IsReal()) {
|
||||
reader_->min_position_ = Utils::Minimum(reader_->min_position_, min_);
|
||||
}
|
||||
reader_->max_position_ = Utils::Maximum(reader_->max_position_, max_);
|
||||
reader_->min_position_ = TokenPosition::Min(reader_->min_position_, min_);
|
||||
reader_->max_position_ = TokenPosition::Max(reader_->max_position_, max_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
+68
-79
@@ -3959,7 +3959,7 @@ static ObjectPtr ThrowTypeError(const TokenPosition token_pos,
|
||||
const AbstractType& dst_type,
|
||||
const String& dst_name) {
|
||||
const Array& args = Array::Handle(Array::New(4));
|
||||
const Smi& pos = Smi::Handle(Smi::New(token_pos.value()));
|
||||
const Smi& pos = Smi::Handle(Smi::New(token_pos.Serialize()));
|
||||
args.SetAt(0, pos);
|
||||
args.SetAt(1, src_value);
|
||||
args.SetAt(2, dst_type);
|
||||
@@ -7640,9 +7640,8 @@ bool Function::IsOptimizable() const {
|
||||
// Native methods don't need to be optimized.
|
||||
return false;
|
||||
}
|
||||
const intptr_t function_length = end_token_pos().Pos() - token_pos().Pos();
|
||||
if (is_optimizable() && (script() != Script::null()) &&
|
||||
(function_length < FLAG_huge_method_cutoff_in_tokens)) {
|
||||
SourceSize() < FLAG_huge_method_cutoff_in_tokens) {
|
||||
// Additional check needed for implicit getters.
|
||||
return (unoptimized_code() == Object::null()) ||
|
||||
(Code::Handle(unoptimized_code()).Size() <
|
||||
@@ -9398,7 +9397,7 @@ StringPtr Function::GetSource() const {
|
||||
if (src.IsNull() || src.Length() == 0) {
|
||||
return Symbols::OptimizedOut().raw();
|
||||
}
|
||||
uint16_t end_char = src.CharAt(end_token_pos().value());
|
||||
uint16_t end_char = src.CharAt(end_token_pos().Pos());
|
||||
if ((end_char == ',') || // Case 1.
|
||||
(end_char == ')') || // Case 2.
|
||||
(end_char == ';' && String::Handle(zone, name())
|
||||
@@ -9662,6 +9661,27 @@ bool Function::MayHaveUncheckedEntryPoint() const {
|
||||
(NeedsTypeArgumentTypeChecks() || NeedsArgumentTypeChecks());
|
||||
}
|
||||
|
||||
intptr_t Function::SourceSize() const {
|
||||
const TokenPosition& start = token_pos();
|
||||
const TokenPosition& end = end_token_pos();
|
||||
if (!end.IsReal() || start.IsNoSource() || start.IsClassifying()) {
|
||||
// No source information, so just return 0.
|
||||
return 0;
|
||||
}
|
||||
if (start.IsSynthetic()) {
|
||||
// Try and approximate the source size using the parent's source size.
|
||||
const auto& parent = Function::Handle(parent_function());
|
||||
ASSERT(!parent.IsNull());
|
||||
const intptr_t parent_size = parent.SourceSize();
|
||||
if (parent_size == 0) {
|
||||
return parent_size;
|
||||
}
|
||||
// Parent must have a real ending position.
|
||||
return parent_size - (parent.end_token_pos().Pos() - end.Pos());
|
||||
}
|
||||
return end.Pos() - start.Pos();
|
||||
}
|
||||
|
||||
const char* Function::ToCString() const {
|
||||
if (IsNull()) {
|
||||
return "Function: null";
|
||||
@@ -11231,31 +11251,6 @@ void Script::SetLocationOffset(intptr_t line_offset,
|
||||
StoreNonPointer(&raw_ptr()->col_offset_, col_offset);
|
||||
}
|
||||
|
||||
// Specialized for AOT compilation, which does this lookup for every token
|
||||
// position that could be part of a stack trace.
|
||||
bool Script::GetTokenLocationUsingLineStarts(TokenPosition target_token_pos,
|
||||
intptr_t* line,
|
||||
intptr_t* column) const {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
return false;
|
||||
#else
|
||||
// Negative positions denote positions that do not correspond to Dart code.
|
||||
if (target_token_pos.value() < 0) return false;
|
||||
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
|
||||
ASSERT(!line_starts_data.IsNull());
|
||||
|
||||
kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
|
||||
line_starts_reader.LocationForPosition(target_token_pos.value(), line,
|
||||
column);
|
||||
// The line and column numbers returned are ordinals, so we shouldn't get 0.
|
||||
ASSERT(*line > 0);
|
||||
ASSERT(*column > 0);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
static bool IsLetter(int32_t c) {
|
||||
return (('A' <= c) && (c <= 'Z')) || (('a' <= c) && (c <= 'z'));
|
||||
@@ -11278,37 +11273,36 @@ void Script::GetTokenLocation(TokenPosition token_pos,
|
||||
intptr_t* line,
|
||||
intptr_t* column,
|
||||
intptr_t* token_len) const {
|
||||
ASSERT(line != NULL);
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
|
||||
LookupSourceAndLineStarts(zone);
|
||||
if (line_starts() == TypedData::null()) {
|
||||
// Scripts in the AOT snapshot do not have a line starts array.
|
||||
*line = -1;
|
||||
if (column != NULL) {
|
||||
*column = -1;
|
||||
}
|
||||
if (token_len != NULL) {
|
||||
*token_len = 1;
|
||||
}
|
||||
return;
|
||||
ASSERT(line != nullptr);
|
||||
// Set up appropriate values for any early returns.
|
||||
*line = -1;
|
||||
if (column != nullptr) {
|
||||
*column = -1;
|
||||
}
|
||||
if (token_len != nullptr) {
|
||||
*token_len = 1;
|
||||
}
|
||||
// Scripts in the AOT snapshot do not have a line starts array.
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (!token_pos.IsReal()) return;
|
||||
|
||||
auto const zone = Thread::Current()->zone();
|
||||
LookupSourceAndLineStarts(zone);
|
||||
const TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
|
||||
kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
|
||||
line_starts_reader.LocationForPosition(token_pos.value(), line, column);
|
||||
if (token_len != NULL) {
|
||||
*token_len = 1;
|
||||
// We don't explicitly save this data: Load the source
|
||||
// and find it from there.
|
||||
const String& source = String::Handle(zone, Source());
|
||||
if (!source.IsNull()) {
|
||||
intptr_t offset = token_pos.value();
|
||||
if (offset < source.Length() && IsIdentStartChar(source.CharAt(offset))) {
|
||||
for (intptr_t i = offset + 1;
|
||||
i < source.Length() && IsIdentChar(source.CharAt(i)); ++i) {
|
||||
++*token_len;
|
||||
}
|
||||
const intptr_t pos = token_pos.Pos();
|
||||
line_starts_reader.LocationForPosition(pos, line, column);
|
||||
if (token_len == nullptr) return;
|
||||
*token_len = 1;
|
||||
// We don't explicitly save this data: Load the source
|
||||
// and find it from there.
|
||||
const String& source = String::Handle(zone, Source());
|
||||
if (!source.IsNull()) {
|
||||
intptr_t offset = pos;
|
||||
if (offset < source.Length() && IsIdentStartChar(source.CharAt(offset))) {
|
||||
for (intptr_t i = offset + 1;
|
||||
i < source.Length() && IsIdentChar(source.CharAt(i)); ++i) {
|
||||
++*token_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11321,16 +11315,10 @@ void Script::TokenRangeAtLine(intptr_t line_number,
|
||||
ASSERT(first_token_index != NULL && last_token_index != NULL);
|
||||
ASSERT(line_number > 0);
|
||||
|
||||
Thread* thread = Thread::Current();
|
||||
Zone* zone = thread->zone();
|
||||
LookupSourceAndLineStarts(zone);
|
||||
if (line_starts() == TypedData::null()) {
|
||||
// Scripts in the AOT snapshot do not have a line starts array.
|
||||
*first_token_index = TokenPosition::kNoSource;
|
||||
*last_token_index = TokenPosition::kNoSource;
|
||||
return;
|
||||
}
|
||||
// Scripts in the AOT snapshot do not have a line starts array.
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
LookupSourceAndLineStarts(zone);
|
||||
const String& source = String::Handle(zone, Source());
|
||||
intptr_t source_length;
|
||||
if (source.IsNull()) {
|
||||
@@ -11342,8 +11330,7 @@ void Script::TokenRangeAtLine(intptr_t line_number,
|
||||
source_length = source.Length();
|
||||
}
|
||||
const TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
|
||||
kernel::KernelLineStartsReader line_starts_reader(line_starts_data,
|
||||
Thread::Current()->zone());
|
||||
kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
|
||||
line_starts_reader.TokenRangeAtLine(source_length, line_number,
|
||||
first_token_index, last_token_index);
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
@@ -14359,8 +14346,8 @@ static int PrintVarInfo(char* buffer,
|
||||
" %-13s level=%-3d"
|
||||
" begin=%-3d end=%d\n",
|
||||
i, LocalVarDescriptors::KindToCString(kind), index,
|
||||
static_cast<int>(info.begin_pos.value()),
|
||||
static_cast<int>(info.end_pos.value()));
|
||||
static_cast<int>(info.begin_pos.Pos()),
|
||||
static_cast<int>(info.end_pos.Pos()));
|
||||
} else if (kind == LocalVarDescriptorsLayout::kContextVar) {
|
||||
return Utils::SNPrint(
|
||||
buffer, len,
|
||||
@@ -16810,18 +16797,19 @@ ContextScopePtr ContextScope::New(intptr_t num_variables, bool is_implicit) {
|
||||
}
|
||||
|
||||
TokenPosition ContextScope::TokenIndexAt(intptr_t scope_index) const {
|
||||
return TokenPosition(Smi::Value(VariableDescAddr(scope_index)->token_pos));
|
||||
return TokenPosition::Deserialize(
|
||||
Smi::Value(VariableDescAddr(scope_index)->token_pos));
|
||||
}
|
||||
|
||||
void ContextScope::SetTokenIndexAt(intptr_t scope_index,
|
||||
TokenPosition token_pos) const {
|
||||
StoreSmi(&VariableDescAddr(scope_index)->token_pos,
|
||||
Smi::New(token_pos.value()));
|
||||
Smi::New(token_pos.Serialize()));
|
||||
}
|
||||
|
||||
TokenPosition ContextScope::DeclarationTokenIndexAt(
|
||||
intptr_t scope_index) const {
|
||||
return TokenPosition(
|
||||
return TokenPosition::Deserialize(
|
||||
Smi::Value(VariableDescAddr(scope_index)->declaration_token_pos));
|
||||
}
|
||||
|
||||
@@ -16829,7 +16817,7 @@ void ContextScope::SetDeclarationTokenIndexAt(
|
||||
intptr_t scope_index,
|
||||
TokenPosition declaration_token_pos) const {
|
||||
StoreSmi(&VariableDescAddr(scope_index)->declaration_token_pos,
|
||||
Smi::New(declaration_token_pos.value()));
|
||||
Smi::New(declaration_token_pos.Serialize()));
|
||||
}
|
||||
|
||||
StringPtr ContextScope::NameAt(intptr_t scope_index) const {
|
||||
@@ -24238,13 +24226,14 @@ static void PrintSymbolicStackFrame(Zone* zone,
|
||||
|
||||
intptr_t line = -1;
|
||||
intptr_t column = -1;
|
||||
if (FLAG_precompiled_mode) {
|
||||
line = token_pos.value();
|
||||
} else if (token_pos.IsSourcePosition()) {
|
||||
ASSERT(!script.IsNull());
|
||||
script.GetTokenLocation(token_pos.SourcePosition(), &line, &column);
|
||||
if (token_pos.IsReal()) {
|
||||
if (FLAG_precompiled_mode) {
|
||||
line = token_pos.Pos();
|
||||
} else {
|
||||
ASSERT(!script.IsNull());
|
||||
script.GetTokenLocation(token_pos, &line, &column);
|
||||
}
|
||||
}
|
||||
|
||||
PrintSymbolicStackFrameIndex(buffer, frame_index);
|
||||
PrintSymbolicStackFrameBody(buffer, function_name, url, line, column);
|
||||
}
|
||||
|
||||
+10
-8
@@ -2954,7 +2954,7 @@ class Function : public Object {
|
||||
|
||||
TokenPosition token_pos() const {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
return TokenPosition();
|
||||
return TokenPosition::kNoSource;
|
||||
#else
|
||||
return raw_ptr()->token_pos_;
|
||||
#endif
|
||||
@@ -2963,7 +2963,7 @@ class Function : public Object {
|
||||
|
||||
TokenPosition end_token_pos() const {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
return TokenPosition();
|
||||
return TokenPosition::kNoSource;
|
||||
#else
|
||||
return raw_ptr()->end_token_pos_;
|
||||
#endif
|
||||
@@ -2976,6 +2976,9 @@ class Function : public Object {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the size of the source for this function.
|
||||
intptr_t SourceSize() const;
|
||||
|
||||
intptr_t num_fixed_parameters() const {
|
||||
return FunctionLayout::PackedNumFixedParameters::decode(
|
||||
raw_ptr()->packed_fields_);
|
||||
@@ -4540,9 +4543,6 @@ class Script : public Object {
|
||||
|
||||
void SetLocationOffset(intptr_t line_offset, intptr_t col_offset) const;
|
||||
|
||||
bool GetTokenLocationUsingLineStarts(TokenPosition token_pos,
|
||||
intptr_t* line,
|
||||
intptr_t* column) const;
|
||||
void GetTokenLocation(TokenPosition token_pos,
|
||||
intptr_t* line,
|
||||
intptr_t* column,
|
||||
@@ -5587,7 +5587,7 @@ class PcDescriptors : public Object {
|
||||
|
||||
if (!FLAG_precompiled_mode) {
|
||||
cur_deopt_id_ += stream.ReadSLEB128();
|
||||
cur_token_pos_ += stream.ReadSLEB128();
|
||||
cur_token_pos_ += stream.ReadSLEB128<int32_t>();
|
||||
}
|
||||
byte_index_ = stream.Position();
|
||||
|
||||
@@ -5600,7 +5600,9 @@ class PcDescriptors : public Object {
|
||||
|
||||
uword PcOffset() const { return cur_pc_offset_; }
|
||||
intptr_t DeoptId() const { return cur_deopt_id_; }
|
||||
TokenPosition TokenPos() const { return TokenPosition(cur_token_pos_); }
|
||||
TokenPosition TokenPos() const {
|
||||
return TokenPosition::Deserialize(cur_token_pos_);
|
||||
}
|
||||
intptr_t TryIndex() const { return cur_try_index_; }
|
||||
intptr_t YieldIndex() const { return cur_yield_index_; }
|
||||
PcDescriptorsLayout::Kind Kind() const {
|
||||
@@ -5630,7 +5632,7 @@ class PcDescriptors : public Object {
|
||||
intptr_t cur_pc_offset_;
|
||||
intptr_t cur_kind_;
|
||||
intptr_t cur_deopt_id_;
|
||||
intptr_t cur_token_pos_;
|
||||
int32_t cur_token_pos_;
|
||||
intptr_t cur_try_index_;
|
||||
intptr_t cur_yield_index_;
|
||||
};
|
||||
|
||||
@@ -808,7 +808,7 @@ void ICData::PrintToJSONArray(const JSONArray& jsarray,
|
||||
|
||||
JSONObject jsobj(&jsarray);
|
||||
jsobj.AddProperty("name", String::Handle(target_name()).ToCString());
|
||||
jsobj.AddProperty("tokenPos", token_pos.value());
|
||||
jsobj.AddProperty("tokenPos", static_cast<intptr_t>(token_pos.Serialize()));
|
||||
// TODO(rmacnak): Figure out how to stringify DeoptReasons().
|
||||
// jsobj.AddProperty("deoptReasons", ...);
|
||||
|
||||
|
||||
+33
-33
@@ -2914,18 +2914,18 @@ ISOLATE_UNIT_TEST_CASE(PcDescriptors) {
|
||||
DescriptorList* builder = new DescriptorList(thread->zone());
|
||||
|
||||
// kind, pc_offset, deopt_id, token_pos, try_index, yield_index
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 1, TokenPosition(20),
|
||||
1, 1);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kDeopt, 20, 2, TokenPosition(30),
|
||||
0, -1);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 30, 3, TokenPosition(40),
|
||||
1, 10);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 4, TokenPosition(40),
|
||||
2, 20);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 5, TokenPosition(80),
|
||||
3, 30);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 80, 6, TokenPosition(150),
|
||||
3, 30);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 1,
|
||||
TokenPosition::Deserialize(20), 1, 1);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kDeopt, 20, 2,
|
||||
TokenPosition::Deserialize(30), 0, -1);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 30, 3,
|
||||
TokenPosition::Deserialize(40), 1, 10);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 4,
|
||||
TokenPosition::Deserialize(40), 2, 20);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 5,
|
||||
TokenPosition::Deserialize(80), 3, 30);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 80, 6,
|
||||
TokenPosition::Deserialize(150), 3, 30);
|
||||
|
||||
PcDescriptors& descriptors = PcDescriptors::Handle();
|
||||
descriptors ^= builder->FinalizePcDescriptors(0);
|
||||
@@ -2945,7 +2945,7 @@ ISOLATE_UNIT_TEST_CASE(PcDescriptors) {
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(1, iter.YieldIndex());
|
||||
EXPECT_EQ(20, iter.TokenPos().value());
|
||||
EXPECT_EQ(20, iter.TokenPos().Pos());
|
||||
EXPECT_EQ(1, iter.TryIndex());
|
||||
EXPECT_EQ(static_cast<uword>(10), iter.PcOffset());
|
||||
EXPECT_EQ(1, iter.DeoptId());
|
||||
@@ -2953,28 +2953,28 @@ ISOLATE_UNIT_TEST_CASE(PcDescriptors) {
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(-1, iter.YieldIndex());
|
||||
EXPECT_EQ(30, iter.TokenPos().value());
|
||||
EXPECT_EQ(30, iter.TokenPos().Pos());
|
||||
EXPECT_EQ(PcDescriptorsLayout::kDeopt, iter.Kind());
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(10, iter.YieldIndex());
|
||||
EXPECT_EQ(40, iter.TokenPos().value());
|
||||
EXPECT_EQ(40, iter.TokenPos().Pos());
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(20, iter.YieldIndex());
|
||||
EXPECT_EQ(40, iter.TokenPos().value());
|
||||
EXPECT_EQ(40, iter.TokenPos().Pos());
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(30, iter.YieldIndex());
|
||||
EXPECT_EQ(80, iter.TokenPos().value());
|
||||
EXPECT_EQ(80, iter.TokenPos().Pos());
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(30, iter.YieldIndex());
|
||||
EXPECT_EQ(150, iter.TokenPos().value());
|
||||
EXPECT_EQ(150, iter.TokenPos().Pos());
|
||||
|
||||
EXPECT_EQ(3, iter.TryIndex());
|
||||
EXPECT_EQ(static_cast<uword>(80), iter.PcOffset());
|
||||
EXPECT_EQ(150, iter.TokenPos().value());
|
||||
EXPECT_EQ(150, iter.TokenPos().Pos());
|
||||
EXPECT_EQ(PcDescriptorsLayout::kOther, iter.Kind());
|
||||
|
||||
EXPECT_EQ(false, iter.MoveNext());
|
||||
@@ -2985,17 +2985,17 @@ ISOLATE_UNIT_TEST_CASE(PcDescriptorsLargeDeltas) {
|
||||
|
||||
// kind, pc_offset, deopt_id, token_pos, try_index
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 1,
|
||||
TokenPosition(200), 1, 10);
|
||||
TokenPosition::Deserialize(200), 1, 10);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kDeopt, 200, 2,
|
||||
TokenPosition(300), 0, -1);
|
||||
TokenPosition::Deserialize(300), 0, -1);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 300, 3,
|
||||
TokenPosition(400), 1, 10);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 4, TokenPosition(0),
|
||||
2, 20);
|
||||
TokenPosition::Deserialize(400), 1, 10);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 4,
|
||||
TokenPosition::Deserialize(0), 2, 20);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 5,
|
||||
TokenPosition(800), 3, 30);
|
||||
TokenPosition::Deserialize(800), 3, 30);
|
||||
builder->AddDescriptor(PcDescriptorsLayout::kOther, 800, 6,
|
||||
TokenPosition(150), 3, 30);
|
||||
TokenPosition::Deserialize(150), 3, 30);
|
||||
|
||||
PcDescriptors& descriptors = PcDescriptors::Handle();
|
||||
descriptors ^= builder->FinalizePcDescriptors(0);
|
||||
@@ -3015,7 +3015,7 @@ ISOLATE_UNIT_TEST_CASE(PcDescriptorsLargeDeltas) {
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(10, iter.YieldIndex());
|
||||
EXPECT_EQ(200, iter.TokenPos().value());
|
||||
EXPECT_EQ(200, iter.TokenPos().Pos());
|
||||
EXPECT_EQ(1, iter.TryIndex());
|
||||
EXPECT_EQ(static_cast<uword>(100), iter.PcOffset());
|
||||
EXPECT_EQ(1, iter.DeoptId());
|
||||
@@ -3023,28 +3023,28 @@ ISOLATE_UNIT_TEST_CASE(PcDescriptorsLargeDeltas) {
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(-1, iter.YieldIndex());
|
||||
EXPECT_EQ(300, iter.TokenPos().value());
|
||||
EXPECT_EQ(300, iter.TokenPos().Pos());
|
||||
EXPECT_EQ(PcDescriptorsLayout::kDeopt, iter.Kind());
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(10, iter.YieldIndex());
|
||||
EXPECT_EQ(400, iter.TokenPos().value());
|
||||
EXPECT_EQ(400, iter.TokenPos().Pos());
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(20, iter.YieldIndex());
|
||||
EXPECT_EQ(0, iter.TokenPos().value());
|
||||
EXPECT_EQ(0, iter.TokenPos().Pos());
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(30, iter.YieldIndex());
|
||||
EXPECT_EQ(800, iter.TokenPos().value());
|
||||
EXPECT_EQ(800, iter.TokenPos().Pos());
|
||||
|
||||
EXPECT_EQ(true, iter.MoveNext());
|
||||
EXPECT_EQ(30, iter.YieldIndex());
|
||||
EXPECT_EQ(150, iter.TokenPos().value());
|
||||
EXPECT_EQ(150, iter.TokenPos().Pos());
|
||||
|
||||
EXPECT_EQ(3, iter.TryIndex());
|
||||
EXPECT_EQ(static_cast<uword>(800), iter.PcOffset());
|
||||
EXPECT_EQ(150, iter.TokenPos().value());
|
||||
EXPECT_EQ(150, iter.TokenPos().Pos());
|
||||
EXPECT_EQ(PcDescriptorsLayout::kOther, iter.Kind());
|
||||
|
||||
EXPECT_EQ(false, iter.MoveNext());
|
||||
|
||||
@@ -174,7 +174,12 @@ void ProfileFunction::TickSourcePosition(TokenPosition token_position,
|
||||
intptr_t i = 0;
|
||||
for (; i < source_position_ticks_.length(); i++) {
|
||||
ProfileFunctionSourcePosition& position = source_position_ticks_[i];
|
||||
if (position.token_pos().value() == token_position.value()) {
|
||||
const intptr_t cmp =
|
||||
TokenPosition::CompareForSorting(position.token_pos(), token_position);
|
||||
if (cmp > 0) {
|
||||
// Found insertion point.
|
||||
break;
|
||||
} else if (cmp == 0) {
|
||||
if (FLAG_trace_profiler_verbose) {
|
||||
OS::PrintErr("Ticking source position %s %s\n",
|
||||
exclusive ? "exclusive" : "inclusive",
|
||||
@@ -184,9 +189,6 @@ void ProfileFunction::TickSourcePosition(TokenPosition token_position,
|
||||
position.Tick(exclusive);
|
||||
return;
|
||||
}
|
||||
if (position.token_pos().value() > token_position.value()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add new one, sorted by token position value.
|
||||
@@ -934,7 +936,7 @@ void ProfileCodeInlinedFunctionsCache::Add(
|
||||
if (cache_entry->inlined_functions.length() == 0) {
|
||||
*inlined_functions = NULL;
|
||||
*inlined_token_positions = NULL;
|
||||
*token_position = cache_entry->token_position = TokenPosition();
|
||||
*token_position = cache_entry->token_position = TokenPosition::kNoSource;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ class ProfileCodeInlinedFunctionsCache : public ZoneAllocated {
|
||||
intptr_t offset;
|
||||
GrowableArray<const Function*> inlined_functions;
|
||||
GrowableArray<TokenPosition> inlined_token_positions;
|
||||
TokenPosition token_position;
|
||||
TokenPosition token_position = TokenPosition::kNoSource;
|
||||
};
|
||||
|
||||
static const intptr_t kCacheSize = 128;
|
||||
|
||||
@@ -282,13 +282,10 @@ class ProfileStackWalker {
|
||||
return NULL;
|
||||
}
|
||||
TokenPosition token_pos = pfsp.token_pos();
|
||||
if (!token_pos.IsSourcePosition()) {
|
||||
if (!token_pos.IsReal()) {
|
||||
// Not a location in a script.
|
||||
return NULL;
|
||||
}
|
||||
if (token_pos.IsSynthetic()) {
|
||||
token_pos = token_pos.FromSynthetic();
|
||||
}
|
||||
|
||||
intptr_t line = 0, column = 0, token_len = 0;
|
||||
script.GetTokenLocation(token_pos, &line, &column, &token_len);
|
||||
@@ -2315,10 +2312,10 @@ ISOLATE_UNIT_TEST_CASE(Profiler_GetSourceReport) {
|
||||
"}\n";
|
||||
|
||||
// Token position of * in `i * i`.
|
||||
const TokenPosition squarePosition = TokenPosition(19);
|
||||
const TokenPosition squarePosition = TokenPosition::Deserialize(19);
|
||||
|
||||
// Token position of the call to `doWork`.
|
||||
const TokenPosition callPosition = TokenPosition(95);
|
||||
const TokenPosition callPosition = TokenPosition::Deserialize(95);
|
||||
|
||||
DisableNativeProfileScope dnps;
|
||||
// Disable profiling for this thread.
|
||||
|
||||
@@ -1919,9 +1919,12 @@ class LocalVarDescriptorsLayout : public ObjectLayout {
|
||||
struct VarInfo {
|
||||
int32_t index_kind = 0; // Bitfield for slot index on stack or in context,
|
||||
// and Entry kind of type VarInfoKind.
|
||||
TokenPosition declaration_pos; // Token position of declaration.
|
||||
TokenPosition begin_pos; // Token position of scope start.
|
||||
TokenPosition end_pos; // Token position of scope end.
|
||||
TokenPosition declaration_pos =
|
||||
TokenPosition::kNoSource; // Token position of declaration.
|
||||
TokenPosition begin_pos =
|
||||
TokenPosition::kNoSource; // Token position of scope start.
|
||||
TokenPosition end_pos =
|
||||
TokenPosition::kNoSource; // Token position of scope end.
|
||||
int16_t scope_id; // Scope to which the variable belongs.
|
||||
|
||||
VarInfoKind kind() const {
|
||||
|
||||
@@ -87,7 +87,7 @@ TypePtr Type::ReadFrom(SnapshotReader* reader,
|
||||
reader->AddBackRef(object_id, &type, kIsDeserialized);
|
||||
|
||||
// Set all non object fields.
|
||||
type.set_token_pos(TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
|
||||
type.set_token_pos(TokenPosition::Deserialize(reader->Read<int32_t>()));
|
||||
const uint8_t combined = reader->Read<uint8_t>();
|
||||
type.set_type_state(combined >> 4);
|
||||
type.set_nullability(static_cast<Nullability>(combined & 0xf));
|
||||
@@ -160,7 +160,7 @@ void TypeLayout::WriteTo(SnapshotWriter* writer,
|
||||
writer->Write<bool>(typeclass_is_in_fullsnapshot);
|
||||
|
||||
// Write out all the non object pointer fields.
|
||||
writer->Write<int32_t>(token_pos_.SnapshotEncode());
|
||||
writer->Write<int32_t>(token_pos_.Serialize());
|
||||
const uint8_t combined = (type_state_ << 4) | nullability_;
|
||||
ASSERT(type_state_ == (combined >> 4));
|
||||
ASSERT(nullability_ == (combined & 0xf));
|
||||
@@ -234,7 +234,7 @@ TypeParameterPtr TypeParameter::ReadFrom(SnapshotReader* reader,
|
||||
|
||||
// Set all non object fields.
|
||||
type_parameter.set_token_pos(
|
||||
TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
|
||||
TokenPosition::Deserialize(reader->Read<int32_t>()));
|
||||
type_parameter.set_index(reader->Read<int16_t>());
|
||||
const uint8_t combined = reader->Read<uint8_t>();
|
||||
type_parameter.set_flags(combined >> 4);
|
||||
@@ -285,7 +285,7 @@ void TypeParameterLayout::WriteTo(SnapshotWriter* writer,
|
||||
writer->WriteTags(writer->GetObjectTags(this));
|
||||
|
||||
// Write out all the non object pointer fields.
|
||||
writer->Write<int32_t>(token_pos_.SnapshotEncode());
|
||||
writer->Write<int32_t>(token_pos_.Serialize());
|
||||
writer->Write<int16_t>(index_);
|
||||
const uint8_t combined = (flags_ << 4) | nullability_;
|
||||
ASSERT(flags_ == (combined >> 4));
|
||||
@@ -637,7 +637,7 @@ LanguageErrorPtr LanguageError::ReadFrom(SnapshotReader* reader,
|
||||
|
||||
// Set all non object fields.
|
||||
language_error.set_token_pos(
|
||||
TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
|
||||
TokenPosition::Deserialize(reader->Read<int32_t>()));
|
||||
language_error.set_report_after_token(reader->Read<bool>());
|
||||
language_error.set_kind(reader->Read<uint8_t>());
|
||||
|
||||
@@ -662,7 +662,7 @@ void LanguageErrorLayout::WriteTo(SnapshotWriter* writer,
|
||||
writer->WriteTags(writer->GetObjectTags(this));
|
||||
|
||||
// Write out all the non object fields.
|
||||
writer->Write<int32_t>(token_pos_.SnapshotEncode());
|
||||
writer->Write<int32_t>(token_pos_.Serialize());
|
||||
writer->Write<bool>(report_after_token_);
|
||||
writer->Write<uint8_t>(kind_);
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ LocalScope::LocalScope(LocalScope* parent, int function_level, int loop_level)
|
||||
function_level_(function_level),
|
||||
loop_level_(loop_level),
|
||||
context_level_(LocalScope::kUninitializedContextLevel),
|
||||
begin_token_pos_(TokenPosition::kNoSourcePos),
|
||||
end_token_pos_(TokenPosition::kNoSourcePos),
|
||||
begin_token_pos_(TokenPosition::kNoSource),
|
||||
end_token_pos_(TokenPosition::kNoSource),
|
||||
variables_(),
|
||||
labels_(),
|
||||
context_variables_(),
|
||||
@@ -779,8 +779,9 @@ void LocalVarDescriptorsBuilder::AddDeoptIdToContextLevelMappings(
|
||||
desc.name = &Symbols::Empty(); // No name.
|
||||
desc.info.set_kind(LocalVarDescriptorsLayout::kContextLevel);
|
||||
desc.info.scope_id = 0;
|
||||
desc.info.begin_pos = TokenPosition(start_deopt_id);
|
||||
desc.info.end_pos = TokenPosition(end_deopt_id);
|
||||
// We repurpose the token position fields to store deopt IDs in this case.
|
||||
desc.info.begin_pos = TokenPosition::Deserialize(start_deopt_id);
|
||||
desc.info.end_pos = TokenPosition::Deserialize(end_deopt_id);
|
||||
desc.info.set_index(start_context_level);
|
||||
Add(desc);
|
||||
|
||||
|
||||
@@ -3283,8 +3283,8 @@ static bool GetSourceReport(Thread* thread, JSONStream* js) {
|
||||
}
|
||||
}
|
||||
SourceReport report(report_set, compile_mode);
|
||||
report.PrintJSON(js, script, TokenPosition(start_pos),
|
||||
TokenPosition(end_pos));
|
||||
report.PrintJSON(js, script, TokenPosition::Deserialize(start_pos),
|
||||
TokenPosition::Deserialize(end_pos));
|
||||
return true;
|
||||
#endif // !DART_PRECOMPILED_RUNTIME
|
||||
}
|
||||
|
||||
+22
-28
@@ -26,8 +26,8 @@ SourceReport::SourceReport(intptr_t report_set, CompileMode compile_mode)
|
||||
compile_mode_(compile_mode),
|
||||
thread_(NULL),
|
||||
script_(NULL),
|
||||
start_pos_(TokenPosition::kNoSource),
|
||||
end_pos_(TokenPosition::kNoSource),
|
||||
start_pos_(TokenPosition::kMinSource),
|
||||
end_pos_(TokenPosition::kMaxSource),
|
||||
profile_(Isolate::Current()),
|
||||
next_script_index_(0) {}
|
||||
|
||||
@@ -51,8 +51,8 @@ void SourceReport::Init(Thread* thread,
|
||||
TokenPosition end_pos) {
|
||||
thread_ = thread;
|
||||
script_ = script;
|
||||
start_pos_ = start_pos;
|
||||
end_pos_ = end_pos;
|
||||
start_pos_ = TokenPosition::Max(start_pos, TokenPosition::kMinSource);
|
||||
end_pos_ = TokenPosition::Min(end_pos, TokenPosition::kMaxSource);
|
||||
ClearScriptTable();
|
||||
if (IsReportRequested(kProfile)) {
|
||||
// Build the profile.
|
||||
@@ -79,10 +79,7 @@ bool SourceReport::ShouldSkipFunction(const Function& func) {
|
||||
// The function is from the wrong script.
|
||||
return true;
|
||||
}
|
||||
if (((start_pos_ > TokenPosition::kMinSource) &&
|
||||
(func.end_token_pos() < start_pos_)) ||
|
||||
((end_pos_ > TokenPosition::kMinSource) &&
|
||||
(func.token_pos() > end_pos_))) {
|
||||
if ((func.end_token_pos() < start_pos_) || (func.token_pos() > end_pos_)) {
|
||||
// The function does not intersect with the requested token range.
|
||||
return true;
|
||||
}
|
||||
@@ -129,10 +126,8 @@ bool SourceReport::ShouldSkipField(const Field& field) {
|
||||
// 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_))) {
|
||||
if ((field.end_token_pos() < start_pos_) ||
|
||||
(field.token_pos() > end_pos_)) {
|
||||
// The field does not intersect with the requested token range.
|
||||
return true;
|
||||
}
|
||||
@@ -195,9 +190,8 @@ void SourceReport::PrintCallSitesData(JSONObject* jsobj,
|
||||
const Function& function,
|
||||
const Code& code) {
|
||||
ASSERT(!code.IsNull());
|
||||
const TokenPosition begin_pos = function.token_pos();
|
||||
const TokenPosition end_pos = function.end_token_pos();
|
||||
|
||||
const TokenPosition& begin_pos = function.token_pos();
|
||||
const TokenPosition& end_pos = function.end_token_pos();
|
||||
ZoneGrowableArray<const ICData*>* ic_data_array =
|
||||
new (zone()) ZoneGrowableArray<const ICData*>();
|
||||
function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
|
||||
@@ -214,8 +208,8 @@ void SourceReport::PrintCallSitesData(JSONObject* jsobj,
|
||||
ASSERT(iter.DeoptId() < ic_data_array->length());
|
||||
const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
|
||||
if (ic_data != NULL) {
|
||||
const TokenPosition token_pos = iter.TokenPos();
|
||||
if ((token_pos < begin_pos) || (token_pos > end_pos)) {
|
||||
const TokenPosition& token_pos = iter.TokenPos();
|
||||
if (!token_pos.IsWithin(begin_pos, end_pos)) {
|
||||
// Does not correspond to a valid source position.
|
||||
continue;
|
||||
}
|
||||
@@ -228,8 +222,8 @@ void SourceReport::PrintCoverageData(JSONObject* jsobj,
|
||||
const Function& function,
|
||||
const Code& code) {
|
||||
ASSERT(!code.IsNull());
|
||||
const TokenPosition begin_pos = function.token_pos();
|
||||
const TokenPosition end_pos = function.end_token_pos();
|
||||
const TokenPosition& begin_pos = function.token_pos();
|
||||
const TokenPosition& end_pos = function.end_token_pos();
|
||||
|
||||
ZoneGrowableArray<const ICData*>* ic_data_array =
|
||||
new (zone()) ZoneGrowableArray<const ICData*>();
|
||||
@@ -241,7 +235,7 @@ void SourceReport::PrintCoverageData(JSONObject* jsobj,
|
||||
const int kCoverageMiss = 1;
|
||||
const int kCoverageHit = 2;
|
||||
|
||||
intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1;
|
||||
intptr_t func_length = function.SourceSize() + 1;
|
||||
GrowableArray<char> coverage(func_length);
|
||||
coverage.SetLength(func_length);
|
||||
for (int i = 0; i < func_length; i++) {
|
||||
@@ -262,8 +256,8 @@ void SourceReport::PrintCoverageData(JSONObject* jsobj,
|
||||
ASSERT(iter.DeoptId() < ic_data_array->length());
|
||||
const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
|
||||
if (ic_data != NULL) {
|
||||
const TokenPosition token_pos = iter.TokenPos();
|
||||
if ((token_pos < begin_pos) || (token_pos > end_pos)) {
|
||||
const TokenPosition& token_pos = iter.TokenPos();
|
||||
if (!token_pos.IsWithin(begin_pos, end_pos)) {
|
||||
// Does not correspond to a valid source position.
|
||||
continue;
|
||||
}
|
||||
@@ -303,9 +297,9 @@ void SourceReport::PrintCoverageData(JSONObject* jsobj,
|
||||
void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj,
|
||||
const Function& func,
|
||||
const Code& code) {
|
||||
const TokenPosition begin_pos = func.token_pos();
|
||||
const TokenPosition end_pos = func.end_token_pos();
|
||||
intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1;
|
||||
const TokenPosition& begin_pos = func.token_pos();
|
||||
const TokenPosition& end_pos = func.end_token_pos();
|
||||
intptr_t func_length = func.SourceSize() + 1;
|
||||
|
||||
BitVector possible(zone(), func_length);
|
||||
|
||||
@@ -320,8 +314,8 @@ void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj,
|
||||
|
||||
PcDescriptors::Iterator iter(descriptors, kSafepointKind);
|
||||
while (iter.MoveNext()) {
|
||||
const TokenPosition token_pos = iter.TokenPos();
|
||||
if ((token_pos < begin_pos) || (token_pos > end_pos)) {
|
||||
const TokenPosition& token_pos = iter.TokenPos();
|
||||
if (!token_pos.IsWithin(begin_pos, end_pos)) {
|
||||
// Does not correspond to a valid source position.
|
||||
continue;
|
||||
}
|
||||
@@ -357,7 +351,7 @@ void SourceReport::PrintProfileData(JSONObject* jsobj,
|
||||
for (intptr_t i = 0; i < profile_function->NumSourcePositions(); i++) {
|
||||
const ProfileFunctionSourcePosition& position =
|
||||
profile_function->GetSourcePosition(i);
|
||||
if (position.token_pos().IsSourcePosition()) {
|
||||
if (position.token_pos().IsReal()) {
|
||||
// Add as an integer.
|
||||
positions.AddValue(position.token_pos().Pos());
|
||||
} else {
|
||||
|
||||
@@ -47,8 +47,8 @@ class SourceReport {
|
||||
// in the isolate.
|
||||
void PrintJSON(JSONStream* js,
|
||||
const Script& script,
|
||||
TokenPosition start_pos = TokenPosition::kNoSource,
|
||||
TokenPosition end_pos = TokenPosition::kNoSource);
|
||||
TokenPosition start_pos = TokenPosition::kMinSource,
|
||||
TokenPosition end_pos = TokenPosition::kMaxSource);
|
||||
|
||||
private:
|
||||
void ClearScriptTable();
|
||||
|
||||
@@ -4,34 +4,29 @@
|
||||
|
||||
#include "vm/token_position.h"
|
||||
|
||||
#include "vm/hash.h"
|
||||
#include "vm/object.h"
|
||||
#include "vm/zone_text_buffer.h"
|
||||
|
||||
namespace dart {
|
||||
|
||||
TokenPosition TokenPosition::SnapshotDecode(int32_t value) {
|
||||
return TokenPosition(static_cast<intptr_t>(value));
|
||||
intptr_t TokenPosition::Hash() const {
|
||||
return FinalizeHash(value_, 31);
|
||||
}
|
||||
|
||||
int32_t TokenPosition::SnapshotEncode() {
|
||||
TokenPosition TokenPosition::Deserialize(int32_t value) {
|
||||
return TokenPosition(value);
|
||||
}
|
||||
|
||||
int32_t TokenPosition::Serialize() const {
|
||||
return static_cast<int32_t>(value_);
|
||||
}
|
||||
|
||||
bool TokenPosition::IsSynthetic() const {
|
||||
if (value_ >= kMinSourcePos) {
|
||||
return false;
|
||||
}
|
||||
if (value_ < kLast.value()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define DEFINE_VALUES(name, value) \
|
||||
const TokenPosition TokenPosition::k##name(value);
|
||||
SENTINEL_TOKEN_DESCRIPTORS(DEFINE_VALUES);
|
||||
#undef DEFINE_VALUES
|
||||
const TokenPosition TokenPosition::kMinSource(kMinSourcePos);
|
||||
|
||||
const TokenPosition TokenPosition::kMaxSource(kMaxSourcePos);
|
||||
|
||||
const char* TokenPosition::ToCString() const {
|
||||
@@ -41,17 +36,16 @@ const char* TokenPosition::ToCString() const {
|
||||
return #name;
|
||||
SENTINEL_TOKEN_DESCRIPTORS(DEFINE_CASE);
|
||||
#undef DEFINE_CASE
|
||||
default: {
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
ASSERT(zone != NULL);
|
||||
if (IsSynthetic()) {
|
||||
// TODO(johnmccutchan): Print synthetic positions differently.
|
||||
return FromSynthetic().ToCString();
|
||||
} else {
|
||||
return OS::SCreate(zone, "%d", value_);
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ASSERT(IsReal() || IsSynthetic());
|
||||
ZoneTextBuffer buffer(Thread::Current()->zone());
|
||||
if (IsSynthetic()) {
|
||||
buffer.AddString("syn:");
|
||||
}
|
||||
buffer.Printf("%" Pd32 "", value_);
|
||||
return buffer.buffer();
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
||||
+116
-89
@@ -17,14 +17,26 @@ namespace dart {
|
||||
// ClassifyingTokenPositions 1 -> -1 - 1
|
||||
// ClassifyingTokenPositions N -> -1 - N
|
||||
//
|
||||
// Synthetically created AstNodes are given real source positions but encoded
|
||||
// as negative numbers from [kSmiMin32, -1 - N]. For example:
|
||||
// Real token positions represent source offsets in some script, and are encoded
|
||||
// as non-negative values which are equal to that offset.
|
||||
//
|
||||
// A source position of 0 in a synthetic AstNode would be encoded as -2 - N.
|
||||
// A source position of 1 in a synthetic AstNode would be encoded as -3 - N.
|
||||
// Synthetically created functions that correspond to user code are given
|
||||
// starting token positions unique from other synthetic functions. The value for
|
||||
// these token positions encode a unique non-negative value as a negative number
|
||||
// within [kSmiMin32, -1 - N).
|
||||
//
|
||||
// All other AstNodes are given real source positions encoded as positive
|
||||
// integers.
|
||||
// For example:
|
||||
// A synthetic token with value 0 is encoded as ((-1 - N) - (0 + 1)) = -2 - N.
|
||||
// A synthetic token with value 1 is encoded as ((-1 - N) - (1 + 1)) = -3 - N.
|
||||
//
|
||||
// Note that the encoded value is _not_ related to any possible real token
|
||||
// position, as two real token positions for different scripts can have the same
|
||||
// value and thus cannot serve as a unique nonce for a synthetic node.
|
||||
//
|
||||
// All other nodes read from user code, such as non-synthetic functions, fields,
|
||||
// etc., are given real starting token positions. All nodes coming from user
|
||||
// code, both real or synthetic, with ending token positions have real ending
|
||||
// token positions.
|
||||
//
|
||||
// This organization allows for ~1 billion token positions.
|
||||
|
||||
@@ -44,56 +56,112 @@ namespace dart {
|
||||
V(DartCodeEpilogue, -13) \
|
||||
V(Last, -14) // Always keep this at the end.
|
||||
|
||||
// A token position representing a debug safe source (real) position,
|
||||
// non-debug safe source (synthetic) positions, or a classifying value used
|
||||
// A token position represents either a debug safe source (real) position,
|
||||
// non-debug safe unique (synthetic) position, or a classifying value used
|
||||
// by the profiler.
|
||||
class TokenPosition {
|
||||
public:
|
||||
TokenPosition() : value_(kNoSource.value()) {}
|
||||
|
||||
explicit TokenPosition(intptr_t value) : value_(value) {}
|
||||
intptr_t Hash() const;
|
||||
|
||||
// Returns whether the token positions are equal. Defined for all token
|
||||
// positions.
|
||||
bool operator==(const TokenPosition& b) const { return value() == b.value(); }
|
||||
|
||||
// Returns whether the token positions are not equal. Defined for all token
|
||||
// positions.
|
||||
bool operator!=(const TokenPosition& b) const { return !(*this == b); }
|
||||
|
||||
bool operator<(const TokenPosition& b) const {
|
||||
// TODO(johnmccutchan): Assert that this is a source position.
|
||||
return value() < b.value();
|
||||
// Returns whether the token position is less than [b]. Only defined for
|
||||
// real token positions.
|
||||
inline bool operator<(const TokenPosition& b) const {
|
||||
return Pos() < b.Pos();
|
||||
}
|
||||
|
||||
bool operator>(const TokenPosition& b) const {
|
||||
// TODO(johnmccutchan): Assert that this is a source position.
|
||||
return b < *this;
|
||||
// Returns whether the token position is greater than [b]. Only defined for
|
||||
// real token positions.
|
||||
inline bool operator>(const TokenPosition& b) const { return b < *this; }
|
||||
|
||||
// Returns whether the token position is less than or equal to [b]. Only
|
||||
// defined for real token positions.
|
||||
inline bool operator<=(const TokenPosition& b) const { return !(*this > b); }
|
||||
|
||||
// Returns whether the token position is greater than or equal to [b]. Only
|
||||
// defined for real token positions.
|
||||
inline bool operator>=(const TokenPosition& b) const { return !(*this < b); }
|
||||
|
||||
// For real token positions, returns whether this is between [a] and [b],
|
||||
// inclusive. If [a] or [b] is non-real, they are treated as less than
|
||||
// any real token position.
|
||||
//
|
||||
// For synthetic token positions, returns whether [a] or [b] equals this.
|
||||
//
|
||||
// For other token positions, always returns false.
|
||||
bool IsWithin(const TokenPosition& a, const TokenPosition& b) const {
|
||||
if (IsReal()) return (a.value() <= value()) && (value() <= b.value());
|
||||
if (IsSynthetic()) return (a == *this) || (b == *this);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator<=(const TokenPosition& b) {
|
||||
// TODO(johnmccutchan): Assert that this is a source position.
|
||||
return !(*this > b);
|
||||
// Returns [a] if both positions are not real, the real position if only one
|
||||
// of [a] and [b] is real, or the minimum position of [a] and [b].
|
||||
static const TokenPosition& Min(const TokenPosition& a,
|
||||
const TokenPosition& b) {
|
||||
if (!b.IsReal()) return a;
|
||||
if (!a.IsReal()) return b;
|
||||
return b.value() < a.value() ? b : a;
|
||||
}
|
||||
// Returns [a] if both positions are not real, the real position if only one
|
||||
// of [a] and [b] is real, or the maximum position of [a] and [b].
|
||||
static const TokenPosition& Max(const TokenPosition& a,
|
||||
const TokenPosition& b) {
|
||||
if (!b.IsReal()) return a;
|
||||
if (!a.IsReal()) return b;
|
||||
return b.value() > a.value() ? b : a;
|
||||
}
|
||||
|
||||
bool operator>=(const TokenPosition& b) {
|
||||
// TODO(johnmccutchan): Assert that this is a source position.
|
||||
return !(*this < b);
|
||||
// Compares two arbitrary source positions for use in sorting, where a
|
||||
// negative return means [a] sorts before [b], a return of 0 means [a] is the
|
||||
// same as [b], and a positive return means [a] sorts after [b].
|
||||
//
|
||||
// Does _not_ correspond to the relational operators on token positions, as
|
||||
// this also allows comparison of kNoSource, classifying, and synthetic token
|
||||
// positions to each other.
|
||||
static intptr_t CompareForSorting(const TokenPosition& a,
|
||||
const TokenPosition& b) {
|
||||
return a.value() - b.value();
|
||||
}
|
||||
|
||||
static const intptr_t kMaxSentinelDescriptors = 64;
|
||||
static constexpr int32_t kMaxSentinelDescriptors = 64;
|
||||
|
||||
#define DECLARE_VALUES(name, value) \
|
||||
static const intptr_t k##name##Pos = value; \
|
||||
static constexpr int32_t k##name##Pos = value; \
|
||||
static const TokenPosition k##name;
|
||||
SENTINEL_TOKEN_DESCRIPTORS(DECLARE_VALUES);
|
||||
#undef DECLARE_VALUES
|
||||
static const intptr_t kMinSourcePos = 0;
|
||||
// Check assumptions used in Is<X> methods below.
|
||||
#define CHECK_VALUES(name, value) \
|
||||
static_assert(k##name##Pos < 0, "Non-negative sentinel descriptor"); \
|
||||
static_assert( \
|
||||
k##name##Pos == kNoSourcePos || k##name##Pos <= kBoxPos, \
|
||||
"Box sentinel descriptor is not greatest classifying sentinel value"); \
|
||||
static_assert(kLastPos <= k##name##Pos, \
|
||||
"Last sentinel descriptor is not least sentinel valu"); \
|
||||
SENTINEL_TOKEN_DESCRIPTORS(CHECK_VALUES);
|
||||
#undef CHECK_VALUES
|
||||
static_assert(kLastPos > -kMaxSentinelDescriptors,
|
||||
"More sentinel descriptors than expected");
|
||||
|
||||
static constexpr int32_t kMinSourcePos = 0;
|
||||
static const TokenPosition kMinSource;
|
||||
static const intptr_t kMaxSourcePos = kSmiMax32 - kMaxSentinelDescriptors - 2;
|
||||
static constexpr int32_t kMaxSourcePos =
|
||||
kSmiMax32 - kMaxSentinelDescriptors - 2;
|
||||
static const TokenPosition kMaxSource;
|
||||
|
||||
// Decode from a snapshot.
|
||||
static TokenPosition SnapshotDecode(int32_t value);
|
||||
// Decode from a serialized form.
|
||||
static TokenPosition Deserialize(int32_t value);
|
||||
|
||||
// Encode for writing into a snapshot.
|
||||
int32_t SnapshotEncode();
|
||||
// Encode into a serialized form.
|
||||
int32_t Serialize() const;
|
||||
|
||||
// Given a real token position, returns the next real token position.
|
||||
TokenPosition Next() {
|
||||
@@ -101,88 +169,47 @@ class TokenPosition {
|
||||
return TokenPosition(value_ + 1);
|
||||
}
|
||||
|
||||
// The raw value.
|
||||
// TODO(johnmccutchan): Make this private.
|
||||
intptr_t value() const { return value_; }
|
||||
|
||||
// Return the source position.
|
||||
intptr_t Pos() const {
|
||||
if (IsSynthetic()) {
|
||||
return FromSynthetic().Pos();
|
||||
}
|
||||
// Return the source position for real token positions.
|
||||
inline intptr_t Pos() const {
|
||||
ASSERT(IsReal());
|
||||
return value_;
|
||||
}
|
||||
|
||||
// Is |this| a classifying sentinel source position?
|
||||
// Classifying positions are used by the profiler to group instructions whose
|
||||
// cost isn't naturally attributable to a source location.
|
||||
bool IsClassifying() const {
|
||||
inline bool IsClassifying() const {
|
||||
return (value_ >= kBox.value()) && (value_ <= kLast.value());
|
||||
}
|
||||
|
||||
// Is |this| the no source position sentinel?
|
||||
bool IsNoSource() const { return *this == kNoSource; }
|
||||
inline bool IsNoSource() const { return value_ == kNoSourcePos; }
|
||||
|
||||
// Is |this| a synthetic source position?
|
||||
// Synthetic source positions are used by the profiler to attribute ticks to a
|
||||
// pieces of source, but ignored by the debugger as potential breakpoints.
|
||||
bool IsSynthetic() const;
|
||||
inline bool IsSynthetic() const { return value_ < kLastPos; }
|
||||
|
||||
// Is |this| a real source position?
|
||||
bool IsReal() const { return value_ >= kMinSourcePos; }
|
||||
|
||||
// Is |this| a source position?
|
||||
bool IsSourcePosition() const { return IsReal() || IsSynthetic(); }
|
||||
|
||||
// Convert |this| into a real source position. Sentinel values remain
|
||||
// unchanged.
|
||||
TokenPosition SourcePosition() const { return FromSynthetic(); }
|
||||
inline bool IsReal() const { return value_ >= kMinSourcePos; }
|
||||
|
||||
// Is |this| a debug pause source position?
|
||||
bool IsDebugPause() const {
|
||||
// Sanity check some values here.
|
||||
ASSERT(kNoSource.value() == kNoSourcePos);
|
||||
ASSERT(kLast.value() < kNoSource.value());
|
||||
ASSERT(kLast.value() > -kMaxSentinelDescriptors);
|
||||
return IsReal();
|
||||
}
|
||||
inline bool IsDebugPause() const { return IsReal(); }
|
||||
|
||||
// Convert |this| into a synthetic source position. Sentinel values remain
|
||||
// unchanged.
|
||||
TokenPosition ToSynthetic() const {
|
||||
const intptr_t value = value_;
|
||||
if (IsClassifying() || IsNoSource()) {
|
||||
return *this;
|
||||
}
|
||||
if (IsSynthetic()) {
|
||||
return *this;
|
||||
}
|
||||
const TokenPosition synthetic_value =
|
||||
TokenPosition((kLast.value() - 1) - value);
|
||||
ASSERT(synthetic_value.IsSynthetic());
|
||||
ASSERT(synthetic_value.value() < kLast.value());
|
||||
return synthetic_value;
|
||||
}
|
||||
|
||||
// Convert |this| from a synthetic source position. Sentinel values remain
|
||||
// unchanged.
|
||||
TokenPosition FromSynthetic() const {
|
||||
const intptr_t synthetic_value = value_;
|
||||
if (IsClassifying() || IsNoSource()) {
|
||||
return *this;
|
||||
}
|
||||
if (!IsSynthetic()) {
|
||||
return *this;
|
||||
}
|
||||
const TokenPosition value =
|
||||
TokenPosition(-synthetic_value + (kLast.value() - 1));
|
||||
ASSERT(!value.IsSynthetic());
|
||||
return value;
|
||||
// Creates a synthetic source position from a non-negative value.
|
||||
static TokenPosition Synthetic(intptr_t value) {
|
||||
ASSERT(value >= 0 && value <= kMaxSourcePos);
|
||||
return TokenPosition((kLastPos - 1) - value);
|
||||
}
|
||||
|
||||
const char* ToCString() const;
|
||||
|
||||
private:
|
||||
explicit TokenPosition(intptr_t value) : value_(value) {}
|
||||
|
||||
// The raw value of this TokenPosition.
|
||||
intptr_t value() const { return value_; }
|
||||
|
||||
int32_t value_;
|
||||
|
||||
DISALLOW_ALLOCATION();
|
||||
|
||||
Reference in New Issue
Block a user