[vm/bytecode] Support SymbolConstant nodes in bytecode pipeline

After https://github.com/dart-lang/sdk/commit/609d2770bea3d4c9dc76b515a52ee325dfb5c50d
constant evaluator produces SymbolConstant nodes.

This CL adds handling of SymbolConstant nodes to bytecode generator by
emitting a new constant pool entry. Constant pool reader is adjusted to
read new constant pool entry.

Change-Id: Idc1e91e765014b3290d80e5a3743448b8a0f472c
Reviewed-on: https://dart-review.googlesource.com/74322
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Régis Crelier <regis@google.com>
This commit is contained in:
Alexander Markov
2018-09-11 17:54:16 +00:00
committed by commit-bot@chromium.org
parent dd2d4af442
commit 3ba5aa8ba7
6 changed files with 92 additions and 10 deletions
-1
View File
@@ -45,7 +45,6 @@ front_end/testcases/*: Skip # These are not tests but input for tests.
front_end/tool/incremental_perf_test: Slow, Pass
kernel/test/closures_test: Slow, Pass
kernel/testcases/*: Skip # These are not tests but input for tests.
vm/test/bytecode/gen_bytecode_test: Fail # Addressed in upcoming CL by amarkov@
vm/test/frontend_server_test: Slow, Pass
vm/test/transformations/type_flow/transformer_test: Slow, Pass
vm/testcases/*: SkipByDesign # These are not tests but input for tests.
+44
View File
@@ -162,6 +162,12 @@ type ConstantEmptyTypeArguments extends ConstantPoolEntry {
Byte tag = 24;
}
type ConstantSymbol extends ConstantPoolEntry {
Byte tag = 25;
Option<LibraryReference> library;
StringReference name;
}
*/
enum ConstantTag {
@@ -190,6 +196,7 @@ enum ConstantTag {
kSubtypeTestCache,
kPartialTearOffInstantiation,
kEmptyTypeArguments,
kSymbol,
}
abstract class ConstantPoolEntry {
@@ -262,6 +269,8 @@ abstract class ConstantPoolEntry {
return new ConstantPartialTearOffInstantiation.readFromBinary(source);
case ConstantTag.kEmptyTypeArguments:
return new ConstantEmptyTypeArguments.readFromBinary(source);
case ConstantTag.kSymbol:
return new ConstantSymbol.readFromBinary(source);
}
throw 'Unexpected constant tag $tag';
}
@@ -1100,6 +1109,41 @@ class ConstantEmptyTypeArguments extends ConstantPoolEntry {
bool operator ==(other) => other is ConstantEmptyTypeArguments;
}
class ConstantSymbol extends ConstantPoolEntry {
final Reference _libraryRef;
final String value;
ConstantSymbol(this._libraryRef, this.value);
@override
ConstantTag get tag => ConstantTag.kSymbol;
Library get library => _libraryRef?.asLibrary;
@override
void writeValueToBinary(BinarySink sink) {
sink.writeCanonicalNameReference(library?.canonicalName);
sink.writeStringReference(value);
}
ConstantSymbol.readFromBinary(BinarySource source)
: _libraryRef = source.readCanonicalNameReference()?.getReference(),
value = source.readStringReference();
@override
String toString() => 'Symbol '
'${library != null ? '$library::' : ''}\'$value\'';
@override
int get hashCode => value.hashCode;
@override
bool operator ==(other) =>
other is ConstantSymbol &&
this.value == other.value &&
this.library == other.library;
}
/// Reserved constant pool entry.
class _ReservedConstantPoolEntry extends ConstantPoolEntry {
const _ReservedConstantPoolEntry();
+4
View File
@@ -2754,6 +2754,10 @@ class ConstantEmitter extends ConstantVisitor<int> {
int visitStringConstant(StringConstant node) =>
cp.add(new ConstantString(node.value));
@override
int visitSymbolConstant(SymbolConstant node) =>
cp.add(new ConstantSymbol(node.libraryReference, node.name));
@override
int visitListConstant(ListConstant node) => cp.add(new ConstantList(
node.typeArgument,
+1
View File
@@ -65,6 +65,7 @@ void test_map_literal<T>(int a, int b, T c) {
void test_symbol() {
print(#test_symbol);
print(#_private_symbol);
}
void test_type_literal<T>() {
+15 -9
View File
@@ -658,22 +658,28 @@ ConstantPool {
Bytecode {
Entry 0
CheckStack
PushConstant CP#2
PushConstant CP#4
IndirectStaticCall 1, CP#3
Drop1
PushConstant CP#0
PushConstant CP#2
IndirectStaticCall 1, CP#1
Drop1
PushConstant CP#3
PushConstant CP#4
IndirectStaticCall 1, CP#1
Drop1
PushConstant CP#5
ReturnTOS
}
ConstantPool {
[0] = Null
[1] = String 'test_symbol'
[2] = Instance dart._internal::Symbol type-args CP#0 {_name: CP#1}
[3] = ArgDesc num-args 1, num-type-args 0, names []
[4] = StaticICData target 'dart.core::print', arg-desc CP#3
[0] = Symbol 'test_symbol'
[1] = ArgDesc num-args 1, num-type-args 0, names []
[2] = StaticICData target 'dart.core::print', arg-desc CP#1
[3] = Symbol #lib::'_private_symbol'
[4] = StaticICData target 'dart.core::print', arg-desc CP#1
[5] = Null
}
]static method test_symbol() → void {
core::print(#test_symbol);
core::print(#_private_symbol);
}
[@vm.bytecode=
Bytecode {
@@ -10,6 +10,7 @@
#include "vm/compiler/assembler/disassembler_kbc.h"
#include "vm/constants_kbc.h"
#include "vm/dart_entry.h"
#include "vm/object_store.h"
#include "vm/timeline.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
@@ -123,6 +124,7 @@ intptr_t BytecodeMetadataHelper::ReadPoolEntries(const Function& function,
kSubtypeTestCache,
kPartialTearOffInstantiation,
kEmptyTypeArguments,
kSymbol,
};
enum InvocationKind {
@@ -141,6 +143,8 @@ intptr_t BytecodeMetadataHelper::ReadPoolEntries(const Function& function,
Class& cls = Class::Handle(helper_->zone_);
String& name = String::Handle(helper_->zone_);
TypeArguments& type_args = TypeArguments::Handle(helper_->zone_);
Class* symbol_class = nullptr;
Field* symbol_name_field = nullptr;
const intptr_t obj_count = pool.Length();
for (intptr_t i = from_index; i < obj_count; ++i) {
const intptr_t tag = helper_->ReadTag();
@@ -513,6 +517,30 @@ intptr_t BytecodeMetadataHelper::ReadPoolEntries(const Function& function,
case ConstantPoolTag::kEmptyTypeArguments:
obj = Object::empty_type_arguments().raw();
break;
case ConstantPoolTag::kSymbol: {
const NameIndex lib_index = helper_->ReadCanonicalNameReference();
obj = Library::null();
if (!H.IsRoot(lib_index)) {
obj = H.LookupLibraryByKernelLibrary(lib_index);
}
const String& symbol = H.DartIdentifier(Library::Cast(obj),
helper_->ReadStringReference());
if (symbol_class == nullptr) {
elem = Library::InternalLibrary();
ASSERT(!elem.IsNull());
symbol_class = &Class::Handle(
helper_->zone_,
Library::Cast(elem).LookupClass(Symbols::Symbol()));
ASSERT(!symbol_class->IsNull());
symbol_name_field = &Field::Handle(
helper_->zone_,
symbol_class->LookupInstanceFieldAllowPrivate(Symbols::_name()));
ASSERT(!symbol_name_field->IsNull());
}
obj = Instance::New(*symbol_class, Heap::kOld);
Instance::Cast(obj).SetField(*symbol_name_field, symbol);
obj = H.Canonicalize(Instance::Cast(obj));
} break;
default:
UNREACHABLE();
}