Keep the line starts delta encoded in the VM heap as well - take 2

This reverts commit adf04d0ac6.

The original change used macros from stdint.h and it failed build on
the linux sdk bot:
https://uberchromegw.corp.google.com/i/client.dart/builders/dart-sdk-linux-be/builds/17348

In the newer version, constants from runtime/platform/globals.h are used
instead of the macros from stdint.h. Constants for int8 have been added as
they were not present already.

Change-Id: Ia4f27613fa5dca2cd6dbfeb37715ea70a85cec95
Reviewed-on: https://dart-review.googlesource.com/25083
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Siva Chandra <sivachandra@google.com>
This commit is contained in:
Siva Chandra 2017-12-01 05:16:48 +00:00 committed by commit-bot@chromium.org
parent 3347b700df
commit 702e4aecb8
5 changed files with 259 additions and 55 deletions

View file

@ -424,6 +424,9 @@ typedef simd128_value_t fpu_register_t;
(((static_cast<uint64_t>(a) << 32) + 0x##b##u))
// Integer constants.
const int8_t kMinInt8 = 0x80;
const int8_t kMaxInt8 = 0x7F;
const uint8_t kMaxUint8 = 0xFF;
const int16_t kMinInt16 = 0x8000;
const int16_t kMaxInt16 = 0x7FFF;
const uint16_t kMaxUint16 = 0xFFFF;

View file

@ -9191,19 +9191,51 @@ String& StreamingFlowGraphBuilder::GetSourceFor(intptr_t index) {
}
RawTypedData* StreamingFlowGraphBuilder::GetLineStartsFor(intptr_t index) {
// Line starts are delta encoded. So get the max delta first so that we
// can store them as tighly as possible.
AlternativeReadingScope alt(reader_);
SetOffset(GetOffsetForSourceInfo(index));
SkipBytes(ReadUInt()); // skip uri.
SkipBytes(ReadUInt()); // skip source.
intptr_t size = ReadUInt(); // read line starts length.
SkipBytes(ReadUInt()); // skip uri.
SkipBytes(ReadUInt()); // skip source.
const intptr_t line_start_count = ReadUInt(); // read number of line start
// entries.
MallocGrowableArray<int32_t> line_starts_array;
TypedData& line_starts_data = TypedData::Handle(
Z, TypedData::New(kTypedDataInt32ArrayCid, size, Heap::kOld));
intptr_t previous_line_start = 0;
for (intptr_t j = 0; j < size; ++j) {
intptr_t line_start = ReadUInt() + previous_line_start;
line_starts_data.SetInt32(j * 4, line_start);
previous_line_start = line_start;
intptr_t max_delta = 0;
for (intptr_t i = 0; i < line_start_count; ++i) {
int32_t delta = ReadUInt();
line_starts_array.Add(delta);
if (delta > max_delta) {
max_delta = delta;
}
}
intptr_t cid;
if (max_delta <= kMaxInt8) {
cid = kTypedDataInt8ArrayCid;
} else if (max_delta <= kMaxInt16) {
cid = kTypedDataInt16ArrayCid;
} else {
cid = kTypedDataInt32ArrayCid;
}
TypedData& line_starts_data =
TypedData::Handle(Z, TypedData::New(cid, line_start_count, Heap::kOld));
for (intptr_t j = 0; j < line_start_count; ++j) {
int32_t line_start = line_starts_array[j];
switch (cid) {
case kTypedDataInt8ArrayCid:
line_starts_data.SetInt8(j, static_cast<int8_t>(line_start));
break;
case kTypedDataInt16ArrayCid:
line_starts_data.SetInt16(j << 1, static_cast<int16_t>(line_start));
break;
case kTypedDataInt32ArrayCid:
line_starts_data.SetInt32(j << 2, line_start);
break;
default:
UNREACHABLE();
}
}
return line_starts_data.raw();
}

View file

@ -28,6 +28,112 @@ bool FieldHasFunctionLiteralInitializer(const Field& field,
return field_helper.FieldHasFunctionLiteralInitializer(start, end);
}
KernelLineStartsReader::KernelLineStartsReader(
const dart::TypedData& line_starts_data,
dart::Zone* zone)
: line_starts_data_(line_starts_data) {
TypedDataElementType type = line_starts_data_.ElementType();
if (type == kInt8ArrayElement) {
helper_ = new KernelInt8LineStartsHelper();
} else if (type == kInt16ArrayElement) {
helper_ = new KernelInt16LineStartsHelper();
} else if (type == kInt32ArrayElement) {
helper_ = new KernelInt32LineStartsHelper();
} else {
UNREACHABLE();
}
}
intptr_t KernelLineStartsReader::LineNumberForPosition(
intptr_t position) const {
intptr_t line_count = line_starts_data_.Length();
intptr_t current_start = 0;
for (intptr_t i = 0; i < line_count; ++i) {
current_start += helper_->At(line_starts_data_, i);
if (current_start > position) {
// If current_start is greater than the desired position, it means that
// it is for the line after |position|. However, since line numbers
// start at 1, we just return |i|.
return i;
}
if (current_start == position) {
return i + 1;
}
}
return line_count;
}
void KernelLineStartsReader::LocationForPosition(intptr_t position,
intptr_t* line,
intptr_t* col) const {
intptr_t line_count = line_starts_data_.Length();
intptr_t current_start = 0;
intptr_t previous_start = 0;
for (intptr_t i = 0; i < line_count; ++i) {
current_start += helper_->At(line_starts_data_, i);
if (current_start > position) {
*line = i;
if (col != NULL) {
*col = position - previous_start + 1;
}
return;
}
if (current_start == position) {
*line = i + 1;
if (col != NULL) {
*col = 1;
}
return;
}
previous_start = current_start;
}
// If the start of any of the lines did not cross |position|,
// then it means the position falls on the last line.
*line = line_count;
if (col != NULL) {
*col = position - current_start + 1;
}
}
void KernelLineStartsReader::TokenRangeAtLine(
intptr_t source_length,
intptr_t line_number,
TokenPosition* first_token_index,
TokenPosition* last_token_index) const {
ASSERT(line_number <= line_starts_data_.Length());
intptr_t cumulative = 0;
for (intptr_t i = 0; i < line_number; ++i) {
cumulative += helper_->At(line_starts_data_, i);
}
*first_token_index = dart::TokenPosition(cumulative);
if (line_number == line_starts_data_.Length()) {
*last_token_index = dart::TokenPosition(source_length);
} else {
*last_token_index = dart::TokenPosition(
cumulative + helper_->At(line_starts_data_, line_number) - 1);
}
}
int32_t KernelLineStartsReader::KernelInt8LineStartsHelper::At(
const dart::TypedData& data,
intptr_t index) const {
return data.GetInt8(index);
}
int32_t KernelLineStartsReader::KernelInt16LineStartsHelper::At(
const dart::TypedData& data,
intptr_t index) const {
return data.GetInt16(index << 1);
}
int32_t KernelLineStartsReader::KernelInt32LineStartsHelper::At(
const dart::TypedData& data,
intptr_t index) const {
return data.GetInt32(index << 2);
}
} // namespace kernel
} // namespace dart

View file

@ -114,6 +114,72 @@ class Program {
DISALLOW_COPY_AND_ASSIGN(Program);
};
class KernelLineStartsReader {
public:
KernelLineStartsReader(const dart::TypedData& line_starts_data,
dart::Zone* zone);
~KernelLineStartsReader() { delete helper_; }
int32_t DeltaAt(intptr_t index) const {
return helper_->At(line_starts_data_, index);
}
intptr_t LineNumberForPosition(intptr_t position) const;
void LocationForPosition(intptr_t position,
intptr_t* line,
intptr_t* col) const;
void TokenRangeAtLine(intptr_t source_length,
intptr_t line_number,
dart::TokenPosition* first_token_index,
dart::TokenPosition* last_token_index) const;
private:
class KernelLineStartsHelper {
public:
KernelLineStartsHelper() {}
virtual ~KernelLineStartsHelper() {}
virtual int32_t At(const dart::TypedData& data, intptr_t index) const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(KernelLineStartsHelper);
};
class KernelInt8LineStartsHelper : public KernelLineStartsHelper {
public:
KernelInt8LineStartsHelper() {}
virtual int32_t At(const dart::TypedData& data, intptr_t index) const;
private:
DISALLOW_COPY_AND_ASSIGN(KernelInt8LineStartsHelper);
};
class KernelInt16LineStartsHelper : public KernelLineStartsHelper {
public:
KernelInt16LineStartsHelper() {}
virtual int32_t At(const dart::TypedData& data, intptr_t index) const;
private:
DISALLOW_COPY_AND_ASSIGN(KernelInt16LineStartsHelper);
};
class KernelInt32LineStartsHelper : public KernelLineStartsHelper {
public:
KernelInt32LineStartsHelper() {}
virtual int32_t At(const dart::TypedData& data, intptr_t index) const;
private:
DISALLOW_COPY_AND_ASSIGN(KernelInt32LineStartsHelper);
};
const dart::TypedData& line_starts_data_;
KernelLineStartsHelper* helper_;
DISALLOW_COPY_AND_ASSIGN(KernelLineStartsReader);
};
ParsedFunction* ParseStaticFieldInitializer(Zone* zone, const Field& field);
bool FieldHasFunctionLiteralInitializer(const Field& field,

View file

@ -31,6 +31,7 @@
#include "vm/hash_table.h"
#include "vm/heap.h"
#include "vm/isolate_reload.h"
#include "vm/kernel.h"
#include "vm/native_symbol.h"
#include "vm/object_store.h"
#include "vm/parser.h"
@ -9224,18 +9225,21 @@ RawGrowableObjectArray* Script::GenerateLineNumberArray() const {
info.Add(line_separator); // New line.
return info.raw();
}
#if !defined(DART_PRECOMPILED_RUNTIME)
intptr_t line_count = line_starts_data.Length();
ASSERT(line_count > 0);
const Array& debug_positions_array = Array::Handle(debug_positions());
intptr_t token_count = debug_positions_array.Length();
int token_index = 0;
kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
intptr_t previous_start = 0;
for (int line_index = 0; line_index < line_count; ++line_index) {
intptr_t start = line_starts_data.GetInt32(line_index * 4);
intptr_t start = previous_start + line_starts_reader.DeltaAt(line_index);
// Output the rest of the tokens if we have no next line.
intptr_t end = TokenPosition::kMaxSourcePos;
if (line_index + 1 < line_count) {
end = line_starts_data.GetInt32((line_index + 1) * 4);
end = start + line_starts_reader.DeltaAt(line_index + 1);
}
bool first = true;
while (token_index < token_count) {
@ -9256,7 +9260,9 @@ RawGrowableObjectArray* Script::GenerateLineNumberArray() const {
info.Add(value);
++token_index;
}
previous_start = start;
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
return info.raw();
}
@ -9490,22 +9496,31 @@ intptr_t Script::GetTokenLineUsingLineStarts(
set_line_starts(line_starts_data);
}
ASSERT(line_starts_data.Length() > 0);
intptr_t offset = target_token_pos.Pos();
intptr_t min = 0;
intptr_t max = line_starts_data.Length() - 1;
if (kind() == RawScript::kKernelTag) {
#if !defined(DART_PRECOMPILED_RUNTIME)
kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
return line_starts_reader.LineNumberForPosition(target_token_pos.value());
#else
return 0;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
} else {
ASSERT(line_starts_data.Length() > 0);
intptr_t offset = target_token_pos.Pos();
intptr_t min = 0;
intptr_t max = line_starts_data.Length() - 1;
// Binary search to find the line containing this offset.
while (min < max) {
int midpoint = (max - min + 1) / 2 + min;
int32_t token_pos = line_starts_data.GetInt32(midpoint * 4);
if (token_pos > offset) {
max = midpoint - 1;
} else {
min = midpoint;
// Binary search to find the line containing this offset.
while (min < max) {
int midpoint = (max - min + 1) / 2 + min;
int32_t token_pos = line_starts_data.GetInt32(midpoint * 4);
if (token_pos > offset) {
max = midpoint - 1;
} else {
min = midpoint;
}
}
return min + 1; // Line numbers start at 1.
}
return min + 1; // Line numbers start at 1.
}
void Script::GetTokenLocation(TokenPosition token_pos,
@ -9528,31 +9543,15 @@ void Script::GetTokenLocation(TokenPosition token_pos,
}
return;
}
#if !defined(DART_PRECOMPILED_RUNTIME)
ASSERT(line_starts_data.Length() > 0);
intptr_t offset = token_pos.value();
intptr_t min = 0;
intptr_t max = line_starts_data.Length() - 1;
// Binary search to find the line containing this offset.
while (min < max) {
intptr_t midpoint = (max - min + 1) / 2 + min;
int32_t value = line_starts_data.GetInt32(midpoint * 4);
if (value > offset) {
max = midpoint - 1;
} else {
min = midpoint;
}
}
*line = min + 1; // Line numbers start at 1.
int32_t min_value = line_starts_data.GetInt32(min * 4);
if (column != NULL) {
*column = offset - min_value + 1;
}
kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
line_starts_reader.LocationForPosition(token_pos.value(), line, column);
if (token_len != NULL) {
// We don't explicitly save this data: Load the source
// and find it from there.
const String& source = String::Handle(zone, Source());
intptr_t offset = token_pos.value();
*token_len = 1;
if (offset < source.Length() &&
Scanner::IsIdentStartChar(source.CharAt(offset))) {
@ -9563,6 +9562,7 @@ void Script::GetTokenLocation(TokenPosition token_pos,
}
}
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
return;
}
@ -9626,16 +9626,13 @@ void Script::TokenRangeAtLine(intptr_t line_number,
*last_token_index = TokenPosition::kNoSource;
return;
}
ASSERT(line_starts_data.Length() >= line_number);
int32_t value = line_starts_data.GetInt32((line_number - 1) * 4);
*first_token_index = TokenPosition(value);
if (line_starts_data.Length() > line_number) {
value = line_starts_data.GetInt32(line_number * 4);
*last_token_index = TokenPosition(value - 1);
} else {
// Length of source is last possible token in this script.
*last_token_index = TokenPosition(String::Handle(Source()).Length());
}
#if !defined(DART_PRECOMPILED_RUNTIME)
kernel::KernelLineStartsReader line_starts_reader(
line_starts_data, Thread::Current()->zone());
line_starts_reader.TokenRangeAtLine(String::Handle(Source()).Length(),
line_number, first_token_index,
last_token_index);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
return;
}