[VM] Use assert assignable implementation for explicit downcasts

This makes explicit downcasts more efficient by re-using the
optimizations we already have for implicit downcasts.

For implicit/explicit as checks we use the symbol to distinguish which
exception to throw if the check fails.  So this does not actually
require unification of _CastError and _TypeError.

Issue https://github.com/dart-lang/sdk/issues/34582
Issue https://github.com/dart-lang/sdk/issues/30632
Issue https://github.com/dart-lang/sdk/issues/30571

Change-Id: I7b8818d2698e249c90a3e1b8790bad69ada649a9
Reviewed-on: https://dart-review.googlesource.com/c/78748
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
Martin Kustermann 2018-10-10 12:36:42 +00:00 committed by commit-bot@chromium.org
parent 17ac151f44
commit 16ddfc1565
16 changed files with 33 additions and 376 deletions

View file

@ -31,6 +31,11 @@ import 'recognized_methods.dart' show RecognizedMethods;
import '../constants_error_reporter.dart' show ForwardConstantEvaluationErrors;
import '../metadata/bytecode.dart';
// This symbol is used as the name in assert assignable's to indicate it comes
// from an explicit 'as' check. This will cause the runtime to throw the right
// exception.
const String symbolForTypeCast = ' in type cast';
void generateBytecode(Component component,
{bool strongMode: true,
bool dropAST: false,
@ -218,10 +223,6 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
Procedure get objectSimpleInstanceOf => _objectSimpleInstanceOf ??=
libraryIndex.getMember('dart:core', 'Object', '_simpleInstanceOf');
Procedure _objectAs;
Procedure get objectAs =>
_objectAs ??= libraryIndex.getMember('dart:core', 'Object', '_as');
Field _closureInstantiatorTypeArguments;
Field get closureInstantiatorTypeArguments =>
_closureInstantiatorTypeArguments ??= libraryIndex.getMember(
@ -1475,16 +1476,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
if (typeEnvironment.isTop(type)) {
return;
}
if (node.isTypeError) {
_genAssertAssignable(type);
} else {
_genPushInstantiatorAndFunctionTypeArguments([type]);
asm.emitPushConstant(cp.add(new ConstantType(type)));
final argDescIndex = cp.add(new ConstantArgDesc(4));
final icdataIndex = cp.add(new ConstantICData(
InvocationKind.method, objectAs.name, argDescIndex));
asm.emitInstanceCall(4, icdataIndex);
}
_genAssertAssignable(type, name: node.isTypeError ? '' : symbolForTypeCast);
}
@override

View file

@ -198,12 +198,13 @@ L1:
Drop1
L2:
Push FP[-5]
PushConstant CP#11
Push FP[-6]
LoadTypeArgumentsField CP#6
Push r0
PushConstant CP#11
InstanceCall 4, CP#12
InstanceCall 1, CP#13
PushConstant CP#12
AssertAssignable 0, CP#13
InstanceCall 1, CP#14
ReturnTOS
PushNull
ReturnTOS
@ -221,8 +222,9 @@ ConstantPool {
[9] = String '32'
[10] = StaticICData target 'dart.core::print', arg-desc CP#4
[11] = Type dart.core::Map<#lib::D::foo3::T2, #lib::D::Q>
[12] = ICData target-name 'dart.core::_as', arg-desc CP#1
[13] = ICData get target-name 'values', arg-desc CP#4
[12] = String ' in type cast'
[13] = SubtypeTestCache
[14] = ICData get target-name 'values', arg-desc CP#4
}
] method foo3<T1 extends core::Object = dynamic, T2 extends core::Object = dynamic>(dynamic z) → dynamic {
if(z is self::A<self::D::foo3::T1>) {
@ -358,10 +360,11 @@ L1:
Drop1
L2:
Push FP[-5]
PushNull
PushNull
PushConstant CP#11
InstanceCall 4, CP#12
PushNull
PushNull
PushConstant CP#12
AssertAssignable 0, CP#13
ReturnTOS
PushNull
ReturnTOS
@ -379,7 +382,8 @@ ConstantPool {
[9] = String '12'
[10] = StaticICData target 'dart.core::print', arg-desc CP#4
[11] = Type #lib::A<dart.core::int>
[12] = ICData target-name 'dart.core::_as', arg-desc CP#7
[12] = String ' in type cast'
[13] = SubtypeTestCache
}
]static method foo1(dynamic x) → dynamic {
if(x is self::B) {

View file

@ -586,26 +586,6 @@ class _CompileTimeError extends Error {
String toString() => _errorMsg;
}
@pragma("vm:entry-point")
dynamic _classRangeAssert(int position, dynamic instance, _Type type, int cid,
int lowerLimit, int upperLimit) {
if ((cid < lowerLimit || cid > upperLimit) && instance != null) {
_TypeError._throwNew(position, instance, type, " in type cast", null);
}
return instance;
}
@pragma("vm:entry-point")
dynamic _classIdEqualsAssert(
int position, dynamic instance, _Type type, int cid, int otherCid) {
if (cid != otherCid && instance != null) {
_TypeError._throwNew(position, instance, type, " in type cast", null);
}
return instance;
}
/// Used by Fasta to report a runtime error when a final field with an
/// initializer is also initialized in a generative constructor.
///

View file

@ -204,68 +204,6 @@ DEFINE_NATIVE_ENTRY(Object_simpleInstanceOf, 2) {
return Bool::Get(is_instance_of).raw();
}
DEFINE_NATIVE_ENTRY(Object_as, 4) {
const Instance& instance =
Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
const TypeArguments& instantiator_type_arguments =
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(1));
const TypeArguments& function_type_arguments =
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(2));
AbstractType& type =
AbstractType::CheckedHandle(zone, arguments->NativeArgAt(3));
ASSERT(type.IsFinalized());
ASSERT(!type.IsMalformed());
ASSERT(!type.IsMalbounded());
Error& bound_error = Error::Handle(zone);
const bool is_instance_of =
instance.IsNull() ||
instance.IsInstanceOf(type, instantiator_type_arguments,
function_type_arguments, &bound_error);
if (FLAG_trace_type_checks) {
const char* result_str = is_instance_of ? "true" : "false";
OS::PrintErr("Object.as: result %s\n", result_str);
const AbstractType& instance_type =
AbstractType::Handle(zone, instance.GetType(Heap::kNew));
OS::PrintErr(" instance type: %s\n",
String::Handle(zone, instance_type.Name()).ToCString());
OS::PrintErr(" cast type: %s\n",
String::Handle(zone, type.Name()).ToCString());
if (!bound_error.IsNull()) {
OS::PrintErr(" bound error: %s\n", bound_error.ToErrorCString());
}
}
if (!is_instance_of) {
DartFrameIterator iterator(thread,
StackFrameIterator::kNoCrossThreadIteration);
StackFrame* caller_frame = iterator.NextFrame();
ASSERT(caller_frame != NULL);
const TokenPosition location = caller_frame->GetTokenPos();
const AbstractType& instance_type =
AbstractType::Handle(zone, instance.GetType(Heap::kNew));
if (!type.IsInstantiated()) {
// Instantiate type before reporting the error.
type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments, kAllFree, NULL, NULL,
NULL, Heap::kNew);
// Note that the instantiated type may be malformed.
}
if (bound_error.IsNull()) {
Exceptions::CreateAndThrowTypeError(location, instance_type, type,
Symbols::InTypeCast(),
Object::null_string());
} else {
ASSERT(isolate->type_checks());
const String& bound_error_message =
String::Handle(zone, String::New(bound_error.ToErrorCString()));
Exceptions::CreateAndThrowTypeError(
location, instance_type, AbstractType::Handle(zone), Symbols::Empty(),
bound_error_message);
}
UNREACHABLE();
}
return instance.raw();
}
DEFINE_NATIVE_ENTRY(AbstractType_toString, 1) {
const AbstractType& type =
AbstractType::CheckedHandle(zone, arguments->NativeArgAt(0));

View file

@ -71,9 +71,4 @@ class Object {
bool _simpleInstanceOfTrue(type) => true;
@pragma("vm:entry-point")
bool _simpleInstanceOfFalse(type) => false;
// Call this function instead of inlining 'as', thus collecting type
// feedback. Returns receiver.
_as(instantiatorTypeArguments, functionTypeArguments, type)
native "Object_as";
}

View file

@ -46,7 +46,7 @@ List<String> expected = [
"$file:${LINE_A+12}:5", // on call to 'print'
"$file:${LINE_A+14}:11", // in 'is'
"$file:${LINE_A+15}:5", // on call to 'print'
"$file:${LINE_A+16}:17", // on 'as'
"$file:${LINE_A+16}:11", // on 'as'
"$file:${LINE_A+17}:11", // on 'isEven'
"$file:${LINE_A+18}:7", // on call to 'print'
"$file:${LINE_A+23}:11", // on 'is!'

View file

@ -23,7 +23,6 @@ namespace dart {
V(Object_haveSameRuntimeType, 2) \
V(Object_instanceOf, 4) \
V(Object_simpleInstanceOf, 2) \
V(Object_as, 4) \
V(Function_apply, 2) \
V(Closure_equals, 2) \
V(Closure_computeHash, 1) \

View file

@ -742,10 +742,6 @@ void AotCallSpecializer::VisitInstanceCall(InstanceCallInstr* instr) {
ReplaceWithInstanceOf(instr);
return;
}
if (Token::IsTypeCastOperator(op_kind)) {
ReplaceWithTypeCast(instr);
return;
}
if (TryInlineFieldAccess(instr)) {
return;
@ -1232,83 +1228,6 @@ bool AotCallSpecializer::TryReplaceInstanceOfWithRangeCheck(
return true;
}
bool AotCallSpecializer::TryReplaceTypeCastWithRangeCheck(
InstanceCallInstr* call,
const AbstractType& type) {
if (precompiler_ == NULL) {
// Loading not complete, can't do CHA yet.
return false;
}
HierarchyInfo* hi = thread()->hierarchy_info();
if (hi == NULL) {
return false;
}
intptr_t lower_limit, upper_limit;
if (!hi->InstanceOfHasClassRange(type, &lower_limit, &upper_limit)) {
return false;
}
Definition* left = call->ArgumentAt(0);
// left as type =>
// _classRangeCheck(pos, left, type, left.cid, lower_limit, upper_limit)
LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left));
InsertBefore(call, left_cid, NULL, FlowGraph::kValue);
ConstantInstr* lower_cid =
flow_graph()->GetConstant(Smi::ZoneHandle(Z, Smi::New(lower_limit)));
ConstantInstr* upper_cid =
flow_graph()->GetConstant(Smi::ZoneHandle(Z, Smi::New(upper_limit)));
ConstantInstr* pos = flow_graph()->GetConstant(
Smi::ZoneHandle(Z, Smi::New(call->token_pos().Pos())));
ZoneGrowableArray<PushArgumentInstr*>* args =
new (Z) ZoneGrowableArray<PushArgumentInstr*>(6);
PushArgumentInstr* arg = new (Z) PushArgumentInstr(new (Z) Value(pos));
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
args->Add(arg);
arg = new (Z) PushArgumentInstr(new (Z) Value(left));
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
args->Add(arg);
arg =
new (Z) PushArgumentInstr(new (Z) Value(flow_graph()->GetConstant(type)));
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
args->Add(arg);
arg = new (Z) PushArgumentInstr(new (Z) Value(left_cid));
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
args->Add(arg);
arg = new (Z) PushArgumentInstr(new (Z) Value(lower_cid));
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
args->Add(arg);
arg = new (Z) PushArgumentInstr(new (Z) Value(upper_cid));
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
args->Add(arg);
const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary());
const String& target_name = Symbols::_classRangeAssert();
const Function& target = Function::ZoneHandle(
Z, dart_internal.LookupFunctionAllowPrivate(target_name));
ASSERT(!target.IsNull());
ASSERT(target.IsRecognized());
ASSERT(target.always_inline());
const intptr_t kTypeArgsLen = 0;
StaticCallInstr* new_call = new (Z) StaticCallInstr(
call->token_pos(), target, kTypeArgsLen,
Object::null_array(), // argument_names
args, call->deopt_id(), call->CallCount(), ICData::kOptimized);
Environment* copy =
call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount());
for (intptr_t i = 0; i < args->length(); ++i) {
copy->PushValue(new (Z) Value((*args)[i]->value()->definition()));
}
call->RemoveEnvironment();
ReplaceCall(call, new_call);
copy->DeepCopyTo(Z, new_call);
return true;
}
void AotCallSpecializer::ReplaceArrayBoundChecks(FlowGraph* flow_graph) {
Zone* zone = Thread::Current()->zone();

View file

@ -32,8 +32,6 @@ class AotCallSpecializer : public CallSpecializer {
virtual bool TryReplaceInstanceOfWithRangeCheck(InstanceCallInstr* call,
const AbstractType& type);
virtual bool TryReplaceTypeCastWithRangeCheck(InstanceCallInstr* call,
const AbstractType& type);
private:
// Attempt to build ICData for call using propagated class-ids.

View file

@ -1458,115 +1458,6 @@ void CallSpecializer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
ReplaceCall(call, instance_of);
}
bool CallSpecializer::TryReplaceTypeCastWithRangeCheck(
InstanceCallInstr* call,
const AbstractType& type) {
// TODO(dartbug.com/30632) does this optimization make sense in JIT?
return false;
}
void CallSpecializer::ReplaceWithTypeCast(InstanceCallInstr* call) {
ASSERT(Token::IsTypeCastOperator(call->token_kind()));
ASSERT(call->type_args_len() == 0);
Definition* left = call->ArgumentAt(0);
Definition* instantiator_type_args = call->ArgumentAt(1);
Definition* function_type_args = call->ArgumentAt(2);
const AbstractType& type =
AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value());
ASSERT(!type.IsMalformedOrMalbounded());
// TODO(dartbug.com/30632) does this optimization make sense in JIT?
if (FLAG_precompiled_mode && TypeCheckAsClassEquality(type)) {
LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left));
InsertBefore(call, left_cid, NULL, FlowGraph::kValue);
const intptr_t type_cid = Class::ZoneHandle(Z, type.type_class()).id();
ConstantInstr* cid =
flow_graph()->GetConstant(Smi::ZoneHandle(Z, Smi::New(type_cid)));
ConstantInstr* pos = flow_graph()->GetConstant(
Smi::ZoneHandle(Z, Smi::New(call->token_pos().Pos())));
ZoneGrowableArray<PushArgumentInstr*>* args =
new (Z) ZoneGrowableArray<PushArgumentInstr*>(5);
PushArgumentInstr* arg = new (Z) PushArgumentInstr(new (Z) Value(pos));
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
args->Add(arg);
arg = new (Z) PushArgumentInstr(new (Z) Value(left));
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
args->Add(arg);
arg = new (Z)
PushArgumentInstr(new (Z) Value(flow_graph()->GetConstant(type)));
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
args->Add(arg);
arg = new (Z) PushArgumentInstr(new (Z) Value(left_cid));
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
args->Add(arg);
arg = new (Z) PushArgumentInstr(new (Z) Value(cid));
InsertBefore(call, arg, NULL, FlowGraph::kEffect);
args->Add(arg);
const Library& dart_internal = Library::Handle(Z, Library::CoreLibrary());
const String& target_name = Symbols::_classIdEqualsAssert();
const Function& target = Function::ZoneHandle(
Z, dart_internal.LookupFunctionAllowPrivate(target_name));
ASSERT(!target.IsNull());
ASSERT(target.IsRecognized());
ASSERT(target.always_inline());
const intptr_t kTypeArgsLen = 0;
StaticCallInstr* new_call = new (Z) StaticCallInstr(
call->token_pos(), target, kTypeArgsLen,
Object::null_array(), // argument_names
args, call->deopt_id(), call->CallCount(), ICData::kStatic);
Environment* copy =
call->env()->DeepCopy(Z, call->env()->Length() - call->ArgumentCount());
for (intptr_t i = 0; i < args->length(); ++i) {
copy->PushValue(new (Z) Value((*args)[i]->value()->definition()));
}
call->RemoveEnvironment();
ReplaceCall(call, new_call);
copy->DeepCopyTo(Z, new_call);
return;
}
if (TryReplaceTypeCastWithRangeCheck(call, type)) {
return;
}
const ICData& unary_checks =
ICData::ZoneHandle(Z, call->ic_data()->AsUnaryClassChecks());
const intptr_t number_of_checks = unary_checks.NumberOfChecks();
if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) {
ZoneGrowableArray<intptr_t>* results =
new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2);
const Bool& as_bool =
Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results));
if (as_bool.raw() == Bool::True().raw()) {
// Guard against repeated speculative inlining.
if (!speculative_policy_->IsAllowedForInlining(call->deopt_id())) {
return;
}
AddReceiverCheck(call);
// Remove the original push arguments.
for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
PushArgumentInstr* push = call->PushArgumentAt(i);
push->ReplaceUsesWith(push->value()->definition());
push->RemoveFromGraph();
}
// Remove call, replace it with 'left'.
call->ReplaceUsesWith(left);
ASSERT(current_iterator()->Current() == call);
current_iterator()->RemoveCurrentFromGraph();
return;
}
}
AssertAssignableInstr* assert_as = new (Z) AssertAssignableInstr(
call->token_pos(), new (Z) Value(left),
new (Z) Value(instantiator_type_args), new (Z) Value(function_type_args),
type, Symbols::InTypeCast(), call->deopt_id());
ReplaceCall(call, assert_as);
}
void CallSpecializer::VisitStaticCall(StaticCallInstr* call) {
if (FlowGraphInliner::TryReplaceStaticCallWithInline(
flow_graph_, current_iterator(), call, speculative_policy_)) {

View file

@ -82,7 +82,6 @@ class CallSpecializer : public FlowGraphVisitor {
bool TryInlineInstanceMethod(InstanceCallInstr* call);
void ReplaceWithInstanceOf(InstanceCallInstr* instr);
void ReplaceWithTypeCast(InstanceCallInstr* instr);
void ReplaceCall(Definition* call, Definition* replacement);
@ -107,9 +106,6 @@ class CallSpecializer : public FlowGraphVisitor {
virtual bool TryReplaceInstanceOfWithRangeCheck(InstanceCallInstr* call,
const AbstractType& type);
virtual bool TryReplaceTypeCastWithRangeCheck(InstanceCallInstr* call,
const AbstractType& type);
virtual bool TryOptimizeStaticCallUsingStaticTypes(StaticCallInstr* call) = 0;
protected:

View file

@ -1525,26 +1525,9 @@ void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) {
ReturnValue(for_value.value());
return;
}
PushArgumentInstr* push_left = PushArgument(for_value.value());
PushArgumentInstr* push_instantiator_type_args =
PushInstantiatorTypeArguments(type, node->token_pos());
PushArgumentInstr* push_function_type_args =
PushFunctionTypeArguments(type, node->token_pos());
ZoneGrowableArray<PushArgumentInstr*>* arguments =
new (Z) ZoneGrowableArray<PushArgumentInstr*>(4);
arguments->Add(push_left);
arguments->Add(push_instantiator_type_args);
arguments->Add(push_function_type_args);
Value* type_arg = Bind(new (Z) ConstantInstr(type));
arguments->Add(PushArgument(type_arg));
const int kTypeArgsLen = 0;
const intptr_t kNumArgsChecked = 1;
InstanceCallInstr* call = new (Z) InstanceCallInstr(
node->token_pos(), Library::PrivateCoreLibName(Symbols::_as()),
node->kind(), arguments, kTypeArgsLen,
Object::null_array(), // No argument names.
kNumArgsChecked, owner()->ic_data_array(), owner()->GetNextDeoptId());
ReturnDefinition(call);
auto assert_assignable = BuildAssertAssignable(
node->token_pos(), for_value.value(), type, Symbols::InTypeCast());
ReturnDefinition(assert_assignable);
}
StrictCompareInstr* EffectGraphVisitor::BuildStrictCompare(

View file

@ -4414,55 +4414,28 @@ Fragment StreamingFlowGraphBuilder::BuildAsExpression(TokenPosition* p) {
TokenPosition position = ReadPosition(); // read position.
if (p != NULL) *p = position;
uint8_t flags = ReadFlags(); // read flags.
const uint8_t flags = ReadFlags(); // read flags.
const bool is_type_error = (flags & (1 << 0)) != 0;
Fragment instructions = BuildExpression(); // read operand.
const AbstractType& type = T.BuildType(); // read type.
// The VM does not like an Object_as call with a dynamic type. We need to
// special case this situation.
const Type& object_type = Type::Handle(Z, Type::ObjectType());
if (type.IsMalformed()) {
instructions += Drop();
instructions += ThrowTypeError();
return instructions;
}
if (type.IsInstantiated() &&
object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) {
} else if (type.IsInstantiated() && type.IsTopType()) {
// We already evaluated the operand on the left and just leave it there as
// the result of the `obj as dynamic` expression.
} else if (is_type_error) {
} else {
// We do not care whether the 'as' cast as implicitly added by the frontend
// or explicitly written by the user, in both cases we use an assert
// assignable.
instructions += LoadLocal(MakeTemporary());
instructions += flow_graph_builder_->AssertAssignable(
position, type, Symbols::Empty(),
instructions += B->AssertAssignable(
position, type,
is_type_error ? Symbols::Empty() : Symbols::InTypeCast(),
AssertAssignableInstr::kInsertedByFrontend);
instructions += Drop();
} else {
instructions += PushArgument();
if (!type.IsInstantiated(kCurrentClass)) {
instructions += LoadInstantiatorTypeArguments();
} else {
instructions += NullConstant();
}
instructions += PushArgument(); // Instantiator type arguments.
if (!type.IsInstantiated(kFunctions)) {
instructions += LoadFunctionTypeArguments();
} else {
instructions += NullConstant();
}
instructions += PushArgument(); // Function type arguments.
instructions += Constant(type);
instructions += PushArgument(); // Type.
instructions += InstanceCall(
position, Library::PrivateCoreLibName(Symbols::_as()), Token::kAS, 4);
}
return instructions;
}

View file

@ -80,11 +80,6 @@ void JitCallSpecializer::VisitInstanceCall(InstanceCallInstr* instr) {
return;
}
if (Token::IsTypeCastOperator(op_kind)) {
ReplaceWithTypeCast(instr);
return;
}
const ICData& unary_checks =
ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());

View file

@ -136,8 +136,6 @@ namespace dart {
0x5aa9888d) \
V(::, _classRangeCheck, ClassRangeCheck, Bool, 0x2ae76b84) \
V(::, _classRangeCheckNegative, ClassRangeCheckNegated, Bool, 0x5acdfb75) \
V(::, _classRangeAssert, ClassRangeAssert, Dynamic, 0x6c77116e) \
V(::, _classIdEqualsAssert, ClassIdEqualsAssert, Dynamic, 0x09e0ae72) \
// List of intrinsics:
@ -439,8 +437,6 @@ namespace dart {
V(::, pow, MathPow, 0x79efc5a2) \
V(::, _classRangeCheck, ClassRangeCheck, 0x2ae76b84) \
V(::, _classRangeCheckNegative, ClassRangeCheckNegated, 0x5acdfb75) \
V(::, _classRangeAssert, ClassRangeAssert, 0x6c77116e) \
V(::, _classIdEqualsAssert, ClassIdEqualsAssert, 0x09e0ae72) \
V(::, _toInt, ConvertMaskedInt, 0x713908fd) \
V(::, _toInt8, ConvertIntToInt8, 0x7484a780) \
V(::, _toUint8, ConvertIntToUint8, 0x0a15b522) \

View file

@ -366,7 +366,6 @@ class ObjectPointerVisitor;
V(_simpleInstanceOf, "_simpleInstanceOf") \
V(_simpleInstanceOfTrue, "_simpleInstanceOfTrue") \
V(_simpleInstanceOfFalse, "_simpleInstanceOfFalse") \
V(_as, "_as") \
V(GetterPrefix, "get:") \
V(SetterPrefix, "set:") \
V(InitPrefix, "init:") \
@ -451,8 +450,6 @@ class ObjectPointerVisitor;
V(options, "options") \
V(_classRangeCheck, "_classRangeCheck") \
V(_classRangeCheckNegative, "_classRangeCheckNegative") \
V(_classRangeAssert, "_classRangeAssert") \
V(_classIdEqualsAssert, "_classIdEqualsAssert") \
V(GetRuntimeType, "get:runtimeType") \
V(HaveSameRuntimeType, "_haveSameRuntimeType") \
V(PrependTypeArguments, "_prependTypeArguments") \