Don't lower to HIndexAssign when the value should be checked

'--checked' and '--strong' accidentally lowered []= to HIndexAssign,
in effect removing the check on the parametric covariant argument.

This makes --checked slower for some array-update-intensive
benchmarks.

Change-Id: I8c36e1db15ac6a98e1ec9ca01b2ebdd3effafc1b
Reviewed-on: https://dart-review.googlesource.com/51802
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
Stephen Adams 2018-04-19 20:15:48 +00:00 committed by commit-bot@chromium.org
parent 3b057dea98
commit 2f9f8088b5
2 changed files with 49 additions and 7 deletions

View file

@ -1122,6 +1122,12 @@ class CommonElements {
_env.lookupLibrary(Uris.dart__native_typed_data, required: true),
'NativeTypedArrayOfInt');
ClassEntity _typedArrayOfDoubleClass;
ClassEntity get typedArrayOfDoubleClass =>
_typedArrayOfDoubleClass ??= _findClass(
_env.lookupLibrary(Uris.dart__native_typed_data, required: true),
'NativeTypedArrayOfDouble');
// From dart:_js_embedded_names
/// Holds the class for the [JsGetName] enum.

View file

@ -122,16 +122,52 @@ class IndexAssignSpecializer extends InvokeDynamicSpecializer {
CompilerOptions options,
CommonElements commonElements,
ClosedWorld closedWorld) {
if (instruction.inputs[1].isMutableIndexable(closedWorld)) {
if (!instruction.inputs[2].isInteger(closedWorld) &&
options.enableTypeAssertions) {
// We want the right checked mode error.
HInstruction receiver = instruction.inputs[1];
HInstruction index = instruction.inputs[2];
if (!receiver.isMutableIndexable(closedWorld)) return null;
if (!index.isInteger(closedWorld) && options.enableTypeAssertions) {
// We want the right checked mode error.
return null;
}
HInstruction value = instruction.inputs[3];
if (options.parameterCheckPolicy.isEmitted) {
if (!_valueParameterCheckAlwaysSucceeds(
instruction, receiver, value, commonElements, closedWorld)) {
return null;
}
return new HIndexAssign(instruction.inputs[1], instruction.inputs[2],
instruction.inputs[3], instruction.selector);
}
return null;
return new HIndexAssign(receiver, index, value, instruction.selector);
}
/// Returns [true] if [value] meets the requirements for being stored into
/// indexable [receiver].
bool _valueParameterCheckAlwaysSucceeds(
HInvokeDynamic instruction,
HInstruction receiver,
HInstruction value,
CommonElements commonElements,
ClosedWorld closedWorld) {
// Handle typed arrays by recognizing the exact implementation of `[]=` and
// checking if [value] has the appropriate type.
if (instruction.element != null) {
ClassEntity cls = instruction.element.enclosingClass;
if (cls == commonElements.typedArrayOfIntClass) {
return value.isInteger(closedWorld);
} else if (cls == commonElements.typedArrayOfDoubleClass) {
return value.isNumber(closedWorld);
}
}
// The type check will pass if it passed before. We know it passed before if
// the value was loaded from the same indexable.
if (value is HIndex) {
if (value.receiver.nonCheck() == receiver.nonCheck()) {
return true;
}
}
return false;
}
}