From 3ba5aa8ba7cc4981642022397e337e6b2fc57ddd Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Tue, 11 Sep 2018 17:54:16 +0000 Subject: [PATCH] [vm/bytecode] Support SymbolConstant nodes in bytecode pipeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Martin Kustermann Reviewed-by: Régis Crelier --- pkg/pkg.status | 1 - pkg/vm/lib/bytecode/constant_pool.dart | 44 +++++++++++++++++++ pkg/vm/lib/bytecode/gen_bytecode.dart | 4 ++ pkg/vm/testcases/bytecode/literals.dart | 1 + .../testcases/bytecode/literals.dart.expect | 24 ++++++---- .../vm/compiler/frontend/bytecode_reader.cc | 28 ++++++++++++ 6 files changed, 92 insertions(+), 10 deletions(-) diff --git a/pkg/pkg.status b/pkg/pkg.status index 8bd525c237e..70629d29352 100644 --- a/pkg/pkg.status +++ b/pkg/pkg.status @@ -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. diff --git a/pkg/vm/lib/bytecode/constant_pool.dart b/pkg/vm/lib/bytecode/constant_pool.dart index 3292962f242..756088540ab 100644 --- a/pkg/vm/lib/bytecode/constant_pool.dart +++ b/pkg/vm/lib/bytecode/constant_pool.dart @@ -162,6 +162,12 @@ type ConstantEmptyTypeArguments extends ConstantPoolEntry { Byte tag = 24; } +type ConstantSymbol extends ConstantPoolEntry { + Byte tag = 25; + Option 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(); diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart index 9ea2d2d9d69..49c6a09d929 100644 --- a/pkg/vm/lib/bytecode/gen_bytecode.dart +++ b/pkg/vm/lib/bytecode/gen_bytecode.dart @@ -2754,6 +2754,10 @@ class ConstantEmitter extends ConstantVisitor { 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, diff --git a/pkg/vm/testcases/bytecode/literals.dart b/pkg/vm/testcases/bytecode/literals.dart index a1266edd022..c4c3ea89aaa 100644 --- a/pkg/vm/testcases/bytecode/literals.dart +++ b/pkg/vm/testcases/bytecode/literals.dart @@ -65,6 +65,7 @@ void test_map_literal(int a, int b, T c) { void test_symbol() { print(#test_symbol); + print(#_private_symbol); } void test_type_literal() { diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect index 1e7fbae105c..22fd2fd306c 100644 --- a/pkg/vm/testcases/bytecode/literals.dart.expect +++ b/pkg/vm/testcases/bytecode/literals.dart.expect @@ -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 { diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc index e5d88c98fff..b0091b78aff 100644 --- a/runtime/vm/compiler/frontend/bytecode_reader.cc +++ b/runtime/vm/compiler/frontend/bytecode_reader.cc @@ -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(); }