5bfe8d454e
In https://github.com/dart-lang/sdk/commit/4fb0c6093879f7383ad597b04b3c89f3384dec19 active class was set in StreamingDartTypeTranslator, but it turns out this is not enough. This CL sets active class in StreamingFlowGraphBuilder; all dependent helper objects should pick it automatically. Fixes https://github.com/dart-lang/sdk/issues/33259 Change-Id: If16afff35de32cbdba23f6260dac0e0fd7e9786a Reviewed-on: https://dart-review.googlesource.com/57524 Reviewed-by: Samir Jindel <sjindel@google.com>
232 lines
7.6 KiB
C++
232 lines
7.6 KiB
C++
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "vm/kernel.h"
|
|
#include "vm/compiler/frontend/kernel_binary_flowgraph.h"
|
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
namespace dart {
|
|
|
|
namespace kernel {
|
|
|
|
bool FieldHasFunctionLiteralInitializer(const Field& field,
|
|
TokenPosition* start,
|
|
TokenPosition* end) {
|
|
Zone* zone = Thread::Current()->zone();
|
|
const Script& script = Script::Handle(zone, field.Script());
|
|
|
|
TranslationHelper translation_helper(Thread::Current());
|
|
translation_helper.InitFromScript(script);
|
|
|
|
StreamingFlowGraphBuilder builder(&translation_helper,
|
|
Script::Handle(zone, field.Script()), zone,
|
|
TypedData::Handle(zone, field.KernelData()),
|
|
field.KernelDataProgramOffset(),
|
|
/* active_class = */ NULL);
|
|
builder.SetOffset(field.kernel_offset());
|
|
kernel::FieldHelper field_helper(&builder);
|
|
field_helper.ReadUntilExcluding(kernel::FieldHelper::kEnd, true);
|
|
return field_helper.FieldHasFunctionLiteralInitializer(start, end);
|
|
}
|
|
|
|
uint32_t KernelSourceFingerprintHelper::CalculateClassFingerprint(
|
|
const Class& klass) {
|
|
Zone* zone = Thread::Current()->zone();
|
|
|
|
// Handle typedefs.
|
|
if (klass.IsTypedefClass()) {
|
|
const Function& func = Function::Handle(zone, klass.signature_function());
|
|
return CalculateFunctionFingerprint(func);
|
|
}
|
|
|
|
String& name = String::Handle(zone, klass.Name());
|
|
const Array& fields = Array::Handle(zone, klass.fields());
|
|
const Array& functions = Array::Handle(zone, klass.functions());
|
|
const Array& interfaces = Array::Handle(zone, klass.interfaces());
|
|
AbstractType& type = AbstractType::Handle(zone);
|
|
|
|
uint32_t hash = 0;
|
|
hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash());
|
|
|
|
type ^= klass.super_type();
|
|
if (!type.IsNull()) {
|
|
name ^= type.Name();
|
|
hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash());
|
|
}
|
|
|
|
type ^= klass.mixin();
|
|
if (!type.IsNull()) {
|
|
name ^= type.Name();
|
|
hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash());
|
|
}
|
|
|
|
Field& field = Field::Handle(zone);
|
|
// Calculate fingerprint for the class fields.
|
|
for (intptr_t i = 0; i < fields.Length(); ++i) {
|
|
field ^= fields.At(i);
|
|
uint32_t fingerprint = CalculateFieldFingerprint(field);
|
|
hash = KernelFingerprintHelper::CalculateHash(hash, fingerprint);
|
|
}
|
|
|
|
// Calculate fingerprint for the class functions.
|
|
Function& func = Function::Handle(zone);
|
|
for (intptr_t i = 0; i < functions.Length(); ++i) {
|
|
func ^= functions.At(i);
|
|
uint32_t fingerprint = CalculateFunctionFingerprint(func);
|
|
hash = KernelFingerprintHelper::CalculateHash(hash, fingerprint);
|
|
}
|
|
|
|
// Calculate fingerprint for the interfaces.
|
|
for (intptr_t i = 0; i < interfaces.Length(); ++i) {
|
|
type ^= interfaces.At(i);
|
|
name ^= type.Name();
|
|
hash = KernelFingerprintHelper::CalculateHash(hash, name.Hash());
|
|
}
|
|
|
|
return hash;
|
|
}
|
|
|
|
uint32_t KernelSourceFingerprintHelper::CalculateFieldFingerprint(
|
|
const Field& field) {
|
|
Thread* thread = Thread::Current();
|
|
Zone* zone = thread->zone();
|
|
const Script& script = Script::Handle(zone, field.Script());
|
|
|
|
TranslationHelper translation_helper(thread);
|
|
translation_helper.InitFromScript(script);
|
|
|
|
KernelFingerprintHelper helper(zone, &translation_helper, script,
|
|
TypedData::Handle(zone, field.KernelData()),
|
|
field.KernelDataProgramOffset());
|
|
helper.SetOffset(field.kernel_offset());
|
|
return helper.CalculateFieldFingerprint();
|
|
}
|
|
|
|
uint32_t KernelSourceFingerprintHelper::CalculateFunctionFingerprint(
|
|
const Function& func) {
|
|
Thread* thread = Thread::Current();
|
|
Zone* zone = thread->zone();
|
|
const Script& script = Script::Handle(zone, func.script());
|
|
|
|
TranslationHelper translation_helper(thread);
|
|
translation_helper.InitFromScript(script);
|
|
|
|
KernelFingerprintHelper helper(zone, &translation_helper, script,
|
|
TypedData::Handle(zone, func.KernelData()),
|
|
func.KernelDataProgramOffset());
|
|
helper.SetOffset(func.kernel_offset());
|
|
return helper.CalculateFunctionFingerprint();
|
|
}
|
|
|
|
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
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|