| Index: runtime/vm/kernel_binary_flowgraph.cc
|
| diff --git a/runtime/vm/kernel_binary_flowgraph.cc b/runtime/vm/kernel_binary_flowgraph.cc
|
| index de0c1f36c8b5a23e938bb8b2679e4c8379a5215f..3fdd7a26aba7510267d8ee8b9e0e6a81561bb2f8 100644
|
| --- a/runtime/vm/kernel_binary_flowgraph.cc
|
| +++ b/runtime/vm/kernel_binary_flowgraph.cc
|
| @@ -38,6 +38,9 @@ Instance& StreamingConstantEvaluator::EvaluateExpression() {
|
| uint8_t payload = 0;
|
| Tag tag = builder_->ReadTag(&payload);
|
| switch (tag) {
|
| + case kStaticGet:
|
| + EvaluateStaticGet();
|
| + break;
|
| case kSymbolLiteral:
|
| EvaluateSymbolLiteral();
|
| break;
|
| @@ -55,6 +58,41 @@ Instance& StreamingConstantEvaluator::EvaluateExpression() {
|
| return dart::Instance::ZoneHandle(Z, result_.raw());
|
| }
|
|
|
| +void StreamingConstantEvaluator::EvaluateStaticGet() {
|
| + builder_->ReadPosition();
|
| + int canonical_name_index = builder_->ReadUInt();
|
| + CanonicalName* target = builder_->GetCanonicalName(canonical_name_index);
|
| +
|
| + if (target->IsField()) {
|
| + const dart::Field& field =
|
| + dart::Field::Handle(Z, H.LookupFieldByKernelField(target));
|
| + if (field.StaticValue() == Object::sentinel().raw() ||
|
| + field.StaticValue() == Object::transition_sentinel().raw()) {
|
| + field.EvaluateInitializer();
|
| + result_ = field.StaticValue();
|
| + result_ = H.Canonicalize(result_);
|
| + field.SetStaticValue(result_, true);
|
| + } else {
|
| + result_ = field.StaticValue();
|
| + }
|
| + } else if (target->IsProcedure()) {
|
| + const Function& function =
|
| + Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
|
| +
|
| + if (target->IsMethod()) {
|
| + Function& closure_function =
|
| + Function::ZoneHandle(Z, function.ImplicitClosureFunction());
|
| + closure_function.set_kernel_function(function.kernel_function());
|
| + result_ = closure_function.ImplicitStaticClosure();
|
| + result_ = H.Canonicalize(result_);
|
| + } else if (target->IsGetter()) {
|
| + UNIMPLEMENTED();
|
| + } else {
|
| + UNIMPLEMENTED();
|
| + }
|
| + }
|
| +}
|
| +
|
| void StreamingConstantEvaluator::EvaluateSymbolLiteral() {
|
| int str_index = builder_->ReadUInt();
|
| const dart::String& symbol_value = builder_->DartSymbol(str_index);
|
| @@ -192,8 +230,8 @@ Fragment StreamingFlowGraphBuilder::BuildAt(intptr_t kernel_offset) {
|
| // return DirectPropertyGet::ReadFrom(reader_);
|
| // case kDirectPropertySet:
|
| // return DirectPropertySet::ReadFrom(reader_);
|
| - // case kStaticGet:
|
| - // return StaticGet::ReadFrom(reader_);
|
| + case kStaticGet:
|
| + return BuildStaticGet();
|
| // case kStaticSet:
|
| // return StaticSet::ReadFrom(reader_);
|
| // case kMethodInvocation:
|
| @@ -273,6 +311,8 @@ intptr_t StreamingFlowGraphBuilder::GetStringTableOffset(intptr_t index) {
|
| if (string_table_offsets_ != NULL && string_table_entries_read_ > index) {
|
| return string_table_offsets_[index];
|
| }
|
| +
|
| + intptr_t saved_offset = ReaderOffset();
|
| if (string_table_offsets_ == NULL) {
|
| reader_->set_offset(4); // Skip kMagicProgramFile - now at string table.
|
| string_table_size_ = ReadListLength();
|
| @@ -292,9 +332,84 @@ intptr_t StreamingFlowGraphBuilder::GetStringTableOffset(intptr_t index) {
|
| string_table_offsets_[string_table_entries_read_] = ReaderOffset();
|
| ++string_table_entries_read_;
|
|
|
| + SetOffset(saved_offset);
|
| return string_table_offsets_[index];
|
| }
|
|
|
| +CanonicalName* StreamingFlowGraphBuilder::GetCanonicalName(intptr_t index) {
|
| + if (index == 0) return NULL;
|
| + --index;
|
| +
|
| + if (canonical_names_ != NULL && canonical_names_entries_read_ > index) {
|
| + return canonical_names_[index];
|
| + }
|
| +
|
| + intptr_t saved_offset = ReaderOffset();
|
| + if (canonical_names_ == NULL) {
|
| + // Find offset from where to read canonical names table.
|
| +
|
| + // First skip the string table:
|
| + // Get first string to make sure we have the table size, get last string and
|
| + // read it to get past the string table.
|
| + // Note that this will also cache all string positions.
|
| + GetStringTableOffset(0);
|
| + SetOffset(GetStringTableOffset(string_table_size_ - 1));
|
| + uint32_t bytes = ReadUInt();
|
| + SkipBytes(bytes);
|
| +
|
| + // Another string table (source URIs)
|
| + intptr_t list_length = ReadListLength();
|
| + for (intptr_t i = 0; i < list_length; ++i) {
|
| + uint32_t bytes = ReadUInt();
|
| + SkipBytes(bytes);
|
| + }
|
| +
|
| + // Source code table
|
| + for (intptr_t i = 0; i < list_length; ++i) {
|
| + // Source code
|
| + intptr_t bytes = ReadUInt();
|
| + SkipBytes(bytes);
|
| +
|
| + // Line starts table
|
| + intptr_t line_count = ReadUInt();
|
| + for (intptr_t j = 0; j < line_count; ++j) {
|
| + ReadUInt();
|
| + }
|
| + }
|
| +
|
| + // Now at canonical names table.
|
| + canonical_names_size_ = ReadUInt();
|
| + canonical_names_ = new CanonicalName*[canonical_names_size_];
|
| + canonical_names_next_offset_ = ReaderOffset();
|
| + }
|
| +
|
| + SetOffset(canonical_names_next_offset_);
|
| + for (; canonical_names_entries_read_ <= index;
|
| + ++canonical_names_entries_read_) {
|
| + intptr_t biased_parent_index = ReadUInt();
|
| + CanonicalName* parent;
|
| + if (biased_parent_index != 0) {
|
| + parent = canonical_names_[biased_parent_index - 1];
|
| + } else {
|
| + if (canonical_names_entries_read_ == 0) {
|
| + parent = CanonicalName::NewRoot();
|
| + } else {
|
| + parent = canonical_names_[0]->parent();
|
| + }
|
| + }
|
| + ASSERT(parent != NULL);
|
| + intptr_t name_index = ReadUInt();
|
| + String* name = KernelString(name_index);
|
| + CanonicalName* canonical_name = parent->AddChild(name);
|
| + canonical_names_[canonical_names_entries_read_] = canonical_name;
|
| + }
|
| +
|
| + canonical_names_next_offset_ = ReaderOffset();
|
| +
|
| + SetOffset(saved_offset);
|
| + return canonical_names_[index];
|
| +}
|
| +
|
| intptr_t StreamingFlowGraphBuilder::ReaderOffset() {
|
| return reader_->offset();
|
| }
|
| @@ -357,6 +472,17 @@ dart::String& StreamingFlowGraphBuilder::DartString(intptr_t str_index) {
|
| return H.DartString(data, bytes);
|
| }
|
|
|
| +String* StreamingFlowGraphBuilder::KernelString(intptr_t str_index) {
|
| + intptr_t savedOffset = ReaderOffset();
|
| +
|
| + SetOffset(GetStringTableOffset(str_index));
|
| + uint32_t bytes = ReadUInt();
|
| + const uint8_t* data = &reader_->buffer()[ReaderOffset()];
|
| +
|
| + SetOffset(savedOffset);
|
| + return new String(data, bytes);
|
| +}
|
| +
|
| Fragment StreamingFlowGraphBuilder::DebugStepCheck(TokenPosition position) {
|
| return flow_graph_builder_->DebugStepCheck(position);
|
| }
|
| @@ -386,6 +512,16 @@ Fragment StreamingFlowGraphBuilder::IntConstant(int64_t value) {
|
| return flow_graph_builder_->IntConstant(value);
|
| }
|
|
|
| +Fragment StreamingFlowGraphBuilder::LoadStaticField() {
|
| + return flow_graph_builder_->LoadStaticField();
|
| +}
|
| +
|
| +Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
|
| + const Function& target,
|
| + intptr_t argument_count) {
|
| + return flow_graph_builder_->StaticCall(position, target, argument_count);
|
| +}
|
| +
|
| Fragment StreamingFlowGraphBuilder::BuildInvalidExpression() {
|
| // The frontend will take care of emitting normal errors (like
|
| // [NoSuchMethodError]s) and only emit [InvalidExpression]s in very special
|
| @@ -393,6 +529,47 @@ Fragment StreamingFlowGraphBuilder::BuildInvalidExpression() {
|
| return ThrowNoSuchMethodError();
|
| }
|
|
|
| +Fragment StreamingFlowGraphBuilder::BuildStaticGet() {
|
| + intptr_t saved_offset = ReaderOffset() - 1; // Include the tag.
|
| + TokenPosition position = ReadPosition();
|
| + int canonical_name_index = ReadUInt();
|
| + CanonicalName* target = GetCanonicalName(canonical_name_index);
|
| +
|
| + if (target->IsField()) {
|
| + const dart::Field& field =
|
| + dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
|
| + if (field.is_const()) {
|
| + SetOffset(saved_offset); // EvaluateExpression needs the tag.
|
| + return Constant(constant_evaluator_.EvaluateExpression());
|
| + } else {
|
| + const dart::Class& owner = dart::Class::Handle(Z, field.Owner());
|
| + const dart::String& getter_name = H.DartGetterName(target);
|
| + const Function& getter =
|
| + Function::ZoneHandle(Z, owner.LookupStaticFunction(getter_name));
|
| + if (getter.IsNull() || !field.has_initializer()) {
|
| + Fragment instructions = Constant(field);
|
| + return instructions + LoadStaticField();
|
| + } else {
|
| + return StaticCall(position, getter, 0);
|
| + }
|
| + }
|
| + } else {
|
| + const Function& function =
|
| + Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
|
| +
|
| + if (target->IsGetter()) {
|
| + return StaticCall(position, function, 0);
|
| + } else if (target->IsMethod()) {
|
| + SetOffset(saved_offset); // EvaluateExpression needs the tag.
|
| + return Constant(constant_evaluator_.EvaluateExpression());
|
| + } else {
|
| + UNIMPLEMENTED();
|
| + }
|
| + }
|
| +
|
| + return Fragment();
|
| +}
|
| +
|
| Fragment StreamingFlowGraphBuilder::BuildSymbolLiteral() {
|
| SkipBytes(-1); // EvaluateExpression needs the tag.
|
| return Constant(constant_evaluator_.EvaluateExpression());
|
|
|