Skip to content

Commit 6349882

Browse files
sstricklcommit-bot@chromium.org
authored andcommitted
[vm/compiler] Add missing truncate calls for parameter names.
Also replace any null flag entries left in the parameter names array to zero Smi values, so that after truncation, no null checks are needed for retrieved flag entries. Now that all appropriate places truncate the parameter names array after setting any required bits, dynamic closure call dispatchers can simply check for any post-name flag entries to detect missing required named parameters if no named arguments were passed. Without the added truncate calls, then vm/dart/minimal_kernel_bytecode_test fails when dynamic closure call dispatchers use that shortcut as seen on patchset 1 of CL 160725. Bug: #40813 Change-Id: I25abd23ad3ce42b03ec5ca29b4e067c162826066 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/160860 Commit-Queue: Tess Strickland <[email protected]> Reviewed-by: Martin Kustermann <[email protected]> Reviewed-by: Alexander Markov <[email protected]>
1 parent 4d18220 commit 6349882

File tree

9 files changed

+132
-126
lines changed

9 files changed

+132
-126
lines changed

runtime/vm/compiler/ffi/call.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,17 @@ FunctionPtr TrampolineFunction(const Function& dart_signature,
3838

3939
// The signature function won't have any names for the parameters. We need to
4040
// assign unique names for scope building and error messages.
41+
function.CreateNameArrayIncludingFlags(Heap::kNew);
4142
const intptr_t num_params = dart_signature.num_fixed_parameters();
42-
const Array& parameter_names = Array::Handle(zone, Array::New(num_params));
4343
for (intptr_t i = 0; i < num_params; ++i) {
4444
if (i == 0) {
4545
name = Symbols::ClosureParameter().raw();
4646
} else {
4747
name = Symbols::NewFormatted(thread, ":ffi_param%" Pd, i);
4848
}
49-
parameter_names.SetAt(i, name);
49+
function.SetParameterNameAt(i, name);
5050
}
51-
function.set_parameter_names(parameter_names);
51+
function.TruncateUnusedParameterFlags();
5252
function.SetFfiCSignature(c_signature);
5353

5454
Type& type = Type::Handle(zone);

runtime/vm/compiler/frontend/bytecode_reader.cc

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -580,17 +580,13 @@ TypePtr BytecodeReaderHelper::ReadFunctionSignature(
580580
func.set_num_fixed_parameters(num_required_params);
581581
func.SetNumOptionalParameters(num_params - num_required_params,
582582
!has_optional_named_params);
583-
const Array& parameter_types =
584-
Array::Handle(Z, Array::New(num_params, Heap::kOld));
585-
func.set_parameter_types(parameter_types);
586-
const Array& parameter_names = Array::Handle(
587-
Z, Array::New(Function::NameArrayLengthIncludingFlags(num_params),
588-
Heap::kOld));
589-
func.set_parameter_names(parameter_names);
583+
func.set_parameter_types(
584+
Array::Handle(Z, Array::New(num_params, Heap::kOld)));
585+
func.CreateNameArrayIncludingFlags(Heap::kOld);
590586

591587
intptr_t i = 0;
592-
parameter_types.SetAt(i, AbstractType::dynamic_type());
593-
parameter_names.SetAt(i, Symbols::ClosureParameter());
588+
func.SetParameterTypeAt(i, AbstractType::dynamic_type());
589+
func.SetParameterNameAt(i, Symbols::ClosureParameter());
594590
++i;
595591

596592
AbstractType& type = AbstractType::Handle(Z);
@@ -602,9 +598,9 @@ TypePtr BytecodeReaderHelper::ReadFunctionSignature(
602598
} else {
603599
name = Symbols::NotNamed().raw();
604600
}
605-
parameter_names.SetAt(i, name);
601+
func.SetParameterNameAt(i, name);
606602
type ^= ReadObject();
607-
parameter_types.SetAt(i, type);
603+
func.SetParameterTypeAt(i, type);
608604
}
609605
if (has_parameter_flags) {
610606
intptr_t num_flags = reader_.ReadUInt();
@@ -2261,7 +2257,6 @@ void BytecodeReaderHelper::ReadFunctionDeclarations(const Class& cls) {
22612257
Object& script_class = Object::Handle(Z);
22622258
Function& function = Function::Handle(Z);
22632259
Array& parameter_types = Array::Handle(Z);
2264-
Array& parameter_names = Array::Handle(Z);
22652260
AbstractType& type = AbstractType::Handle(Z);
22662261

22672262
name = cls.ScrubbedName();
@@ -2371,10 +2366,7 @@ void BytecodeReaderHelper::ReadFunctionDeclarations(const Class& cls) {
23712366

23722367
parameter_types = Array::New(num_params, Heap::kOld);
23732368
function.set_parameter_types(parameter_types);
2374-
2375-
parameter_names = Array::New(
2376-
Function::NameArrayLengthIncludingFlags(num_params), Heap::kOld);
2377-
function.set_parameter_names(parameter_names);
2369+
function.CreateNameArrayIncludingFlags(Heap::kOld);
23782370

23792371
intptr_t param_index = 0;
23802372
if (!is_static) {
@@ -2398,9 +2390,9 @@ void BytecodeReaderHelper::ReadFunctionDeclarations(const Class& cls) {
23982390

23992391
for (; param_index < num_params; ++param_index) {
24002392
name ^= ReadObject();
2401-
parameter_names.SetAt(param_index, name);
2393+
function.SetParameterNameAt(param_index, name);
24022394
type ^= ReadObject();
2403-
parameter_types.SetAt(param_index, type);
2395+
function.SetParameterTypeAt(param_index, type);
24042396
}
24052397

24062398
type ^= ReadObject();
@@ -3109,6 +3101,7 @@ void BytecodeReaderHelper::ParseForwarderFunction(
31093101
}
31103102
}
31113103
}
3104+
function.TruncateUnusedParameterFlags();
31123105

31133106
if (has_forwarding_stub_target) {
31143107
const intptr_t cp_index = reader_.ReadUInt();

runtime/vm/compiler/frontend/kernel_to_il.cc

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,6 +2006,25 @@ Fragment FlowGraphBuilder::BuildClosureCallHasRequiredNamedArgumentsCheck(
20062006
// Required named arguments only exist if null_safety is enabled.
20072007
if (!Isolate::Current()->null_safety()) return Fragment();
20082008

2009+
if (descriptor.NamedCount() == 0) {
2010+
static_assert(compiler::target::kNumParameterFlags == 1,
2011+
"IL builder assumes only one flag bit per parameter");
2012+
// No named args were provided, so check for any required named params.
2013+
// Here, we assume that the only parameter flag saved is the required bit
2014+
// for named parameters. If this changes, we'll need to check each flag
2015+
// entry appropriately for any set required bits.
2016+
Fragment has_any;
2017+
has_any += LoadLocal(vars->num_max_params);
2018+
has_any += LoadLocal(vars->parameter_names);
2019+
has_any += LoadNativeField(Slot::Array_length());
2020+
TargetEntryInstr *no_required, *has_required;
2021+
has_any += BranchIfEqual(&no_required, &has_required);
2022+
2023+
Fragment(has_required) + Goto(nsm);
2024+
2025+
return Fragment(has_any.entry, no_required);
2026+
}
2027+
20092028
// Loop over the indexes of the named parameters of the function, checking
20102029
// whether the named parameter at that index is required. If it is, then
20112030
// check whether it matches any of the names in the ArgumentsDescriptor.
@@ -2050,39 +2069,20 @@ Fragment FlowGraphBuilder::BuildClosureCallHasRequiredNamedArgumentsCheck(
20502069

20512070
Fragment(invalid_index) + Goto(done);
20522071

2053-
// Otherwise, we need to retrieve the value. If it's null, then this index
2054-
// and others that map to the same entry cannot be required (but later ones
2055-
// may be).
2072+
// Otherwise, we need to retrieve the value and check the appropriate bit.
20562073
loop_body.current = valid_index;
20572074
loop_body += LoadLocal(vars->parameter_names);
20582075
loop_body += LoadLocal(temp); // Index into parameter names array.
20592076
loop_body += LoadIndexed(compiler::target::kWordSize);
2060-
// Store the result so we can use it in the non-null branch. We can reuse
2061-
// :expr_temp as we don't need the names index once we've gotten the contents.
2062-
loop_body += StoreLocal(TokenPosition::kNoSource, temp);
2063-
TargetEntryInstr *null_smi, *flags_smi;
2064-
loop_body += BranchIfNull(&null_smi, &flags_smi);
2065-
2066-
// If it was null, then skip forward to the first named parameter index that
2067-
// would map to the next parameter names index, since no other indices that
2068-
// map to the same entry can be set either.
2069-
Fragment skip_ahead(null_smi);
2070-
skip_ahead += LoadLocal(vars->current_param_index);
2071-
skip_ahead += IntConstant(compiler::target::kNumParameterFlagsPerElement);
2072-
skip_ahead += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
2073-
skip_ahead += StoreLocal(TokenPosition::kNoSource, vars->current_param_index);
2074-
skip_ahead += Drop();
2075-
skip_ahead += Goto(loop);
2076-
2077-
// If not null, see if any of the flag bits are set for the given named
2078-
// parameter. If so, this named parameter is required.
2079-
loop_body.current = flags_smi;
2080-
loop_body += LoadLocal(temp); // Flag bits loaded from parameter names array.
20812077
loop_body += LoadLocal(vars->current_param_index);
20822078
loop_body += IntConstant(compiler::target::kNumParameterFlagsPerElement - 1);
20832079
loop_body += SmiBinaryOp(Token::kBIT_AND);
2080+
if (compiler::target::kNumParameterFlags > 1) {
2081+
loop_body += IntConstant(compiler::target::kNumParameterFlags);
2082+
loop_body += SmiBinaryOp(Token::kMUL, /*is_truncating=*/false);
2083+
}
20842084
loop_body += SmiBinaryOp(Token::kSHR);
2085-
loop_body += IntConstant(1);
2085+
loop_body += IntConstant(1 << compiler::target::kRequiredNamedParameterFlag);
20862086
loop_body += SmiBinaryOp(Token::kBIT_AND);
20872087
loop_body += IntConstant(0);
20882088
TargetEntryInstr *not_set, *set;

runtime/vm/compiler/frontend/kernel_translation_helper.cc

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -735,8 +735,7 @@ void TranslationHelper::SetupFieldAccessorFunction(
735735
function.set_num_fixed_parameters(parameter_count);
736736
function.set_parameter_types(
737737
Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
738-
function.set_parameter_names(
739-
Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
738+
function.CreateNameArrayIncludingFlags(Heap::kNew);
740739

741740
intptr_t pos = 0;
742741
if (is_method) {
@@ -3075,32 +3074,25 @@ void TypeTranslator::BuildFunctionType(bool simple) {
30753074
all_count = positional_count;
30763075
}
30773076

3078-
const intptr_t all_count_with_receiver = all_count + 1;
3079-
const Array& parameter_types =
3080-
Array::Handle(Z, Array::New(all_count_with_receiver, Heap::kOld));
3081-
signature_function.set_parameter_types(parameter_types);
3082-
const Array& parameter_names = Array::Handle(
3083-
Z, Array::New(simple ? all_count_with_receiver
3084-
: Function::NameArrayLengthIncludingFlags(
3085-
all_count_with_receiver),
3086-
Heap::kOld));
3087-
signature_function.set_parameter_names(parameter_names);
3077+
// The additional first parameter is the receiver type (set to dynamic).
3078+
signature_function.set_num_fixed_parameters(1 + required_count);
3079+
signature_function.SetNumOptionalParameters(
3080+
all_count - required_count, positional_count > required_count);
3081+
3082+
signature_function.set_parameter_types(
3083+
Array::Handle(Z, Array::New(1 + all_count, Heap::kOld)));
3084+
signature_function.CreateNameArrayIncludingFlags(Heap::kOld);
30883085

30893086
intptr_t pos = 0;
3090-
parameter_types.SetAt(pos, AbstractType::dynamic_type());
3091-
parameter_names.SetAt(pos, H.DartSymbolPlain("_receiver_"));
3087+
signature_function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
3088+
signature_function.SetParameterNameAt(pos, H.DartSymbolPlain("_receiver_"));
30923089
++pos;
30933090
for (intptr_t i = 0; i < positional_count; ++i, ++pos) {
30943091
BuildTypeInternal(); // read ith positional parameter.
3095-
parameter_types.SetAt(pos, result_);
3096-
parameter_names.SetAt(pos, H.DartSymbolPlain("noname"));
3092+
signature_function.SetParameterTypeAt(pos, result_);
3093+
signature_function.SetParameterNameAt(pos, H.DartSymbolPlain("noname"));
30973094
}
30983095

3099-
// The additional first parameter is the receiver type (set to dynamic).
3100-
signature_function.set_num_fixed_parameters(1 + required_count);
3101-
signature_function.SetNumOptionalParameters(
3102-
all_count - required_count, positional_count > required_count);
3103-
31043096
if (!simple) {
31053097
const intptr_t named_count =
31063098
helper_->ReadListLength(); // read named_parameters list length.
@@ -3109,15 +3101,15 @@ void TypeTranslator::BuildFunctionType(bool simple) {
31093101
String& name = H.DartSymbolObfuscate(helper_->ReadStringReference());
31103102
BuildTypeInternal(); // read named_parameters[i].type.
31113103
const uint8_t flags = helper_->ReadFlags(); // read flags
3112-
parameter_types.SetAt(pos, result_);
3113-
parameter_names.SetAt(pos, name);
3104+
signature_function.SetParameterTypeAt(pos, result_);
3105+
signature_function.SetParameterNameAt(pos, name);
31143106
if (!apply_legacy_erasure_ &&
31153107
(flags & static_cast<uint8_t>(NamedTypeFlags::kIsRequired)) != 0) {
31163108
signature_function.SetIsRequiredAt(pos);
31173109
}
31183110
}
3119-
signature_function.TruncateUnusedParameterFlags();
31203111
}
3112+
signature_function.TruncateUnusedParameterFlags();
31213113

31223114
if (!simple) {
31233115
helper_->SkipOptionalDartType(); // read typedef type.
@@ -3554,10 +3546,7 @@ void TypeTranslator::SetupFunctionParameters(
35543546

35553547
function.set_parameter_types(
35563548
Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
3557-
const Array& parameter_names = Array::Handle(
3558-
Z, Array::New(Function::NameArrayLengthIncludingFlags(parameter_count),
3559-
Heap::kOld));
3560-
function.set_parameter_names(parameter_names);
3549+
function.CreateNameArrayIncludingFlags(Heap::kOld);
35613550
intptr_t pos = 0;
35623551
if (is_method) {
35633552
ASSERT(!klass.IsNull());

runtime/vm/compiler/runtime_api.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -299,17 +299,22 @@ extern const word kOldPageSizeInWords;
299299
extern const word kOldPageMask;
300300

301301
static constexpr intptr_t kObjectAlignment = ObjectAlignment::kObjectAlignment;
302-
// Parameter flags are stored in Smis. In particular, there is one flag (the
303-
// required flag), but we want ensure that the number of bits stored per Smi is
304-
// a power of two so we can simply uses shift to convert the parameter index to
305-
// calculate both the parameter flag index in the parameter names array to get
306-
// the packed flags and which bit in the packed flags to check.
302+
303+
// Note: if other flags are added, then change the check for required parameters
304+
// when no named arguments are provided in
305+
// FlowGraphBuilder::BuildClosureCallHasRequiredNamedArgumentsCheck, since it
306+
// assumes there are no flag slots when no named parameters are required.
307+
enum ParameterFlags {
308+
kRequiredNamedParameterFlag,
309+
kNumParameterFlags,
310+
};
311+
// Parameter flags are stored in Smis. To ensure shifts and masks can be used to
312+
// calculate both the parameter flag index in the parameter names array and
313+
// which bit to check, kNumParameterFlagsPerElement should be a power of two.
307314
static constexpr intptr_t kNumParameterFlagsPerElementLog2 =
308-
kBitsPerWordLog2 - 1;
315+
kBitsPerWordLog2 - kNumParameterFlags;
309316
static constexpr intptr_t kNumParameterFlagsPerElement =
310317
1 << kNumParameterFlagsPerElementLog2;
311-
// Thus, in the untagged Smi value, only the lowest kNumParameterFlagsPerElement
312-
// bits are used for flags, with the other bits currently unused.
313318
static_assert(kNumParameterFlagsPerElement <= kSmiBits,
314319
"kNumParameterFlagsPerElement should fit in a Smi");
315320

runtime/vm/kernel_loader.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2431,11 +2431,11 @@ FunctionPtr CreateFieldInitializerFunction(Thread* thread,
24312431
initializer_fun.set_num_fixed_parameters(1);
24322432
initializer_fun.set_parameter_types(
24332433
Array::Handle(zone, Array::New(1, Heap::kOld)));
2434-
initializer_fun.set_parameter_names(
2435-
Array::Handle(zone, Array::New(1, Heap::kOld)));
2434+
initializer_fun.CreateNameArrayIncludingFlags(Heap::kOld);
24362435
initializer_fun.SetParameterTypeAt(
24372436
0, AbstractType::Handle(zone, field_owner.DeclarationType()));
24382437
initializer_fun.SetParameterNameAt(0, Symbols::This());
2438+
initializer_fun.TruncateUnusedParameterFlags();
24392439
}
24402440
initializer_fun.set_result_type(AbstractType::Handle(zone, field.type()));
24412441
initializer_fun.set_is_reflectable(false);

0 commit comments

Comments
 (0)