Skip to content

Commit 9690693

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm/bytecode] Fix writing and reading of nested function types in bytecode
Fixes #37486 Change-Id: Id6b10288cf9afeddb8a9972eb1dd455184b15789 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108740 Reviewed-by: Régis Crelier <[email protected]> Reviewed-by: Ryan Macnak <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
1 parent 55078c0 commit 9690693

File tree

7 files changed

+107
-15
lines changed

7 files changed

+107
-15
lines changed

pkg/vm/lib/bytecode/object_table.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,11 +2012,10 @@ class _NodeVisitor extends Visitor<ObjectHandle> {
20122012

20132013
@override
20142014
ObjectHandle visitFunctionType(FunctionType node) {
2015-
final typeParameters = new List<_TypeParameterHandle>.generate(
2016-
node.typeParameters.length,
2017-
(i) => objectTable.getOrAddObject(new _TypeParameterHandle(null, i)));
2015+
final int numEnclosingTypeParameters = _typeParameters.length;
20182016
for (int i = 0; i < node.typeParameters.length; ++i) {
2019-
_typeParameters[node.typeParameters[i]] = typeParameters[i];
2017+
_typeParameters[node.typeParameters[i]] = objectTable.getOrAddObject(
2018+
new _TypeParameterHandle(null, numEnclosingTypeParameters + i));
20202019
}
20212020

20222021
final positionalParams = new List<_TypeHandle>();

runtime/vm/compiler/frontend/bytecode_reader.cc

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ void BytecodeReaderHelper::ReadCode(const Function& function,
201201
ASSERT(code_offset > 0);
202202

203203
AlternativeReadingScope alt(&reader_, code_offset);
204+
// This scope is needed to set active_class_->enclosing_ which is used to
205+
// assign parent function for function types.
206+
ActiveEnclosingFunctionScope active_enclosing_function(active_class_,
207+
&function);
204208

205209
const intptr_t flags = reader_.ReadUInt();
206210
const bool has_exceptions_table =
@@ -251,7 +255,7 @@ void BytecodeReaderHelper::ReadCode(const Function& function,
251255
// TODO(alexmarkov): allocate deopt_ids for closures separately
252256
DeoptIdScope deopt_id_scope(thread_, 0);
253257

254-
ReadConstantPool(function, pool);
258+
ReadConstantPool(function, pool, 0);
255259
}
256260

257261
// Read bytecode and attach to function.
@@ -653,7 +657,17 @@ void BytecodeReaderHelper::ReadTypeParametersDeclaration(
653657
// Do not set type parameters for factories, as VM uses class type
654658
// parameters instead.
655659
parameterized_function.set_type_parameters(type_parameters);
656-
function_type_type_parameters_ = &type_parameters;
660+
if (parameterized_function.IsSignatureFunction()) {
661+
if (function_type_type_parameters_ == nullptr) {
662+
function_type_type_parameters_ = &type_parameters;
663+
} else {
664+
function_type_type_parameters_ = &TypeArguments::Handle(
665+
Z, function_type_type_parameters_->ConcatenateTypeParameters(
666+
Z, type_parameters));
667+
}
668+
} else {
669+
ASSERT(function_type_type_parameters_ == nullptr);
670+
}
657671
}
658672

659673
// Step b) Fill in the bounds of all [TypeParameter]s.
@@ -664,8 +678,9 @@ void BytecodeReaderHelper::ReadTypeParametersDeclaration(
664678
}
665679
}
666680

667-
void BytecodeReaderHelper::ReadConstantPool(const Function& function,
668-
const ObjectPool& pool) {
681+
intptr_t BytecodeReaderHelper::ReadConstantPool(const Function& function,
682+
const ObjectPool& pool,
683+
intptr_t start_index) {
669684
TIMELINE_DURATION(Thread::Current(), CompilerVerbose,
670685
"BytecodeReaderHelper::ReadConstantPool");
671686

@@ -721,7 +736,7 @@ void BytecodeReaderHelper::ReadConstantPool(const Function& function,
721736
String& name = String::Handle(Z);
722737
const String* simpleInstanceOf = nullptr;
723738
const intptr_t obj_count = pool.Length();
724-
for (intptr_t i = 0; i < obj_count; ++i) {
739+
for (intptr_t i = start_index; i < obj_count; ++i) {
725740
const intptr_t tag = reader_.ReadTag();
726741
switch (tag) {
727742
case ConstantPoolTag::kInvalid:
@@ -799,11 +814,30 @@ void BytecodeReaderHelper::ReadConstantPool(const Function& function,
799814
intptr_t closure_index = reader_.ReadUInt();
800815
obj = closures_->At(closure_index);
801816
ASSERT(obj.IsFunction());
802-
} break;
817+
// Set current entry.
818+
pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
819+
ObjectPool::Patchability::kNotPatchable);
820+
pool.SetObjectAt(i, obj);
821+
822+
// This scope is needed to set active_class_->enclosing_ which is used
823+
// to assign parent function for function types.
824+
ActiveEnclosingFunctionScope active_enclosing_function(
825+
active_class_, &Function::Cast(obj));
826+
827+
// Read constant pool until corresponding EndClosureFunctionScope.
828+
i = ReadConstantPool(function, pool, i + 1);
829+
830+
// Proceed with the rest of entries.
831+
continue;
832+
}
803833
case ConstantPoolTag::kEndClosureFunctionScope: {
804-
// Entry is not used and set to null.
834+
// EndClosureFunctionScope entry is not used and set to null.
805835
obj = Object::null();
806-
} break;
836+
pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
837+
ObjectPool::Patchability::kNotPatchable);
838+
pool.SetObjectAt(i, obj);
839+
return i;
840+
}
807841
case ConstantPoolTag::kNativeEntry: {
808842
name = ReadString();
809843
obj = NativeEntry(function, name);
@@ -854,6 +888,8 @@ void BytecodeReaderHelper::ReadConstantPool(const Function& function,
854888
ObjectPool::Patchability::kNotPatchable);
855889
pool.SetObjectAt(i, obj);
856890
}
891+
892+
return obj_count - 1;
857893
}
858894

859895
RawBytecode* BytecodeReaderHelper::ReadBytecode(const ObjectPool& pool) {
@@ -1405,6 +1441,11 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) {
14051441
: Function::null_function(),
14061442
TokenPosition::kNoSource));
14071443

1444+
// This scope is needed to set active_class_->enclosing_ which is used
1445+
// to assign parent function for function types.
1446+
ActiveEnclosingFunctionScope active_enclosing_function(
1447+
active_class_, &signature_function);
1448+
14081449
return ReadFunctionSignature(
14091450
signature_function, (flags & kFlagHasOptionalPositionalParams) != 0,
14101451
(flags & kFlagHasOptionalNamedParams) != 0,
@@ -1710,6 +1751,12 @@ RawObject* BytecodeReaderHelper::ReadType(intptr_t tag) {
17101751
? *active_class_->enclosing
17111752
: Function::null_function(),
17121753
TokenPosition::kNoSource));
1754+
1755+
// This scope is needed to set active_class_->enclosing_ which is used to
1756+
// assign parent function for function types.
1757+
ActiveEnclosingFunctionScope active_enclosing_function(
1758+
active_class_, &signature_function);
1759+
17131760
// TODO(alexmarkov): skip type finalization
17141761
return ReadFunctionSignature(
17151762
signature_function, (flags & kFlagHasOptionalPositionalParams) != 0,
@@ -3014,8 +3061,6 @@ RawError* BytecodeReader::ReadFunctionBytecode(Thread* thread,
30143061

30153062
ActiveClassScope active_class_scope(&active_class, &klass);
30163063
ActiveMemberScope active_member(&active_class, &outermost_function);
3017-
ActiveTypeParametersScope active_type_params(&active_class, function,
3018-
zone);
30193064

30203065
BytecodeComponentData bytecode_component(
30213066
&Array::Handle(zone, translation_helper.GetBytecodeComponent()));

runtime/vm/compiler/frontend/bytecode_reader.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,13 @@ class BytecodeReaderHelper : public ValueObject {
183183
void ReadTypeParametersDeclaration(const Class& parameterized_class,
184184
const Function& parameterized_function);
185185

186-
void ReadConstantPool(const Function& function, const ObjectPool& pool);
186+
// Read portion of constant pool corresponding to one function/closure.
187+
// Start with [start_index], and stop when reaching EndClosureFunctionScope.
188+
// Return index of the last read constant pool entry.
189+
intptr_t ReadConstantPool(const Function& function,
190+
const ObjectPool& pool,
191+
intptr_t start_index);
192+
187193
RawBytecode* ReadBytecode(const ObjectPool& pool);
188194
void ReadExceptionsTable(const Bytecode& bytecode, bool has_exceptions_table);
189195
void ReadSourcePositions(const Bytecode& bytecode, bool has_source_positions);

runtime/vm/compiler/frontend/kernel_translation_helper.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,23 @@ class ActiveMemberScope {
11991199
DISALLOW_COPY_AND_ASSIGN(ActiveMemberScope);
12001200
};
12011201

1202+
class ActiveEnclosingFunctionScope {
1203+
public:
1204+
ActiveEnclosingFunctionScope(ActiveClass* active_class,
1205+
const Function* enclosing)
1206+
: active_class_(active_class), saved_(*active_class) {
1207+
active_class_->enclosing = enclosing;
1208+
}
1209+
1210+
~ActiveEnclosingFunctionScope() { *active_class_ = saved_; }
1211+
1212+
private:
1213+
ActiveClass* active_class_;
1214+
ActiveClass saved_;
1215+
1216+
DISALLOW_COPY_AND_ASSIGN(ActiveEnclosingFunctionScope);
1217+
};
1218+
12021219
class ActiveTypeParametersScope {
12031220
public:
12041221
// Set the local type parameters of the ActiveClass to be exactly all type

runtime/vm/object.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4957,6 +4957,26 @@ RawTypeArguments* TypeArguments::Prepend(Zone* zone,
49574957
return result.Canonicalize();
49584958
}
49594959

4960+
RawTypeArguments* TypeArguments::ConcatenateTypeParameters(
4961+
Zone* zone,
4962+
const TypeArguments& other) const {
4963+
ASSERT(!IsNull() && !other.IsNull());
4964+
const intptr_t this_len = Length();
4965+
const intptr_t other_len = other.Length();
4966+
const auto& result = TypeArguments::Handle(
4967+
zone, TypeArguments::New(this_len + other_len, Heap::kNew));
4968+
auto& type = AbstractType::Handle(zone);
4969+
for (intptr_t i = 0; i < this_len; ++i) {
4970+
type = TypeAt(i);
4971+
result.SetTypeAt(i, type);
4972+
}
4973+
for (intptr_t i = 0; i < other_len; ++i) {
4974+
type = other.TypeAt(i);
4975+
result.SetTypeAt(this_len + i, type);
4976+
}
4977+
return result.raw();
4978+
}
4979+
49604980
RawString* TypeArguments::SubvectorName(intptr_t from_index,
49614981
intptr_t len,
49624982
NameVisibility name_visibility) const {

runtime/vm/object.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6536,6 +6536,10 @@ class TypeArguments : public Instance {
65366536
intptr_t other_length,
65376537
intptr_t total_length) const;
65386538

6539+
// Concatenate [this] and [other] vectors of type parameters.
6540+
RawTypeArguments* ConcatenateTypeParameters(Zone* zone,
6541+
const TypeArguments& other) const;
6542+
65396543
// Check if the subvector of length 'len' starting at 'from_index' of this
65406544
// type argument vector consists solely of DynamicType, ObjectType, or
65416545
// VoidType.

tests/corelib_2/corelib_2.status

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ apply_generic_function_test: SkipByDesign # Function.apply with named args
104104
apply_test: Skip # Uses new Symbol via symbolMapToStringMap helper
105105
dynamic_nosuchmethod_test: SkipByDesign # Expects names in NSM
106106
error_stack_trace1_test: SkipByDesign # Expects unobfuscated stack trace
107+
type_tostring_test: SkipByDesign # Expects names in Type.toString()
107108

108109
# All static_tests have expected compile-time errors.
109110
[ $compiler != app_jitk && $compiler != dart2analyzer && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk && $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $compiler != fasta ]

0 commit comments

Comments
 (0)