diff --git a/src/compiler.ts b/src/compiler.ts index a2b313603b..8af8f06ab7 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -7683,23 +7683,26 @@ export class Compiler extends DiagnosticEmitter { ), false // managedness is irrelevant here, isn't interrupted ) ); - let allInstances: Set | null; + let allInstances: Class[] | null; if (instance.isInterface) { - allInstances = instance.implementers; + let implementers = instance.implementers; + // Ensure interfaces are filtered out, since their class IDs will never be + // seen in actual objects. + allInstances = implementers + ? Set_values(implementers).filter(implementer => implementer.kind == ElementKind.Class) + : null; } else { - allInstances = new Set(); - allInstances.add(instance); let extenders = instance.extenders; if (extenders) { - for (let _values = Set_values(extenders), i = 0, k = _values.length; i < k; ++i) { - let extender = _values[i]; - allInstances.add(extender); - } + allInstances = Set_values(extenders); + allInstances.push(instance); + } else { + allInstances = [instance]; } } if (allInstances) { - for (let _values = Set_values(allInstances), i = 0, k = _values.length; i < k; ++i) { - let instance = _values[i]; + for (let i = 0, k = allInstances.length; i < k; ++i) { + let instance = unchecked(allInstances[i]); stmts.push( module.br("is_instance", module.binary(BinaryOp.EqI32, diff --git a/src/extra/ast.ts b/src/extra/ast.ts index ebe9217f90..5916aeb66c 100644 --- a/src/extra/ast.ts +++ b/src/extra/ast.ts @@ -1297,12 +1297,16 @@ export class ASTBuilder { } sb.push(">"); } - let extendsType = node.extendsType; - if (extendsType) { + let implementsTypes = node.implementsTypes; + if (implementsTypes && implementsTypes.length > 0) { sb.push(" extends "); - this.visitTypeNode(extendsType); + this.visitTypeNode(implementsTypes[0]); + for (let i = 1, k = implementsTypes.length; i < k; ++i) { + sb.push(", "); + this.visitTypeNode(implementsTypes[i]); + } } - // must not have implementsTypes + // must not have extendsType sb.push(" {\n"); let indentLevel = ++this.indentLevel; let members = node.members; diff --git a/src/parser.ts b/src/parser.ts index 3bcee57681..be8713bcde 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1703,20 +1703,40 @@ export class Parser extends DiagnosticEmitter { } let extendsType: NamedTypeNode | null = null; + let implementsTypes: NamedTypeNode[] | null = null; if (tn.skip(Token.Extends)) { - let type = this.parseType(tn); - if (!type) return null; - if (type.kind != NodeKind.NamedType) { - this.error( - DiagnosticCode.Identifier_expected, - type.range - ); - return null; + if (isInterface) { + do { + let type = this.parseType(tn); + if (!type) return null; + if (type.kind != NodeKind.NamedType) { + this.error( + DiagnosticCode.Identifier_expected, + type.range + ); + return null; + } + // Note: Even though the keyword is "extends", the base interfaces are stored in + // the implementsTypes field, as that's already an array that can be used. + // When an InterfacePrototype is created, the base InterfacePrototypes are + // stored in the interfacePrototypes field for the same reason. + if (!implementsTypes) implementsTypes = [type]; + else implementsTypes.push(type); + } while (tn.skip(Token.Comma)); + } else { + let type = this.parseType(tn); + if (!type) return null; + if (type.kind != NodeKind.NamedType) { + this.error( + DiagnosticCode.Identifier_expected, + type.range + ); + return null; + } + extendsType = type; } - extendsType = type; } - let implementsTypes: NamedTypeNode[] | null = null; if (tn.skip(Token.Implements)) { if (isInterface) { this.error( @@ -1752,14 +1772,14 @@ export class Parser extends DiagnosticEmitter { let members = new Array(); let declaration: ClassDeclaration; if (isInterface) { - assert(!implementsTypes); + assert(!extendsType); declaration = Node.createInterfaceDeclaration( identifier, decorators, flags, typeParameters, - extendsType, null, + implementsTypes, members, tn.range(startPos, tn.pos) ); diff --git a/src/program.ts b/src/program.ts index 829cffee05..adc634ed29 100644 --- a/src/program.ts +++ b/src/program.ts @@ -1129,7 +1129,7 @@ export class Program extends DiagnosticEmitter { break; } case NodeKind.InterfaceDeclaration: { - this.initializeInterface(statement, file, queuedExtends); + this.initializeInterface(statement, file, queuedImplements); break; } case NodeKind.NamespaceDeclaration: { @@ -1302,64 +1302,45 @@ export class Program extends DiagnosticEmitter { } } - // resolve prototypes of extended classes or interfaces + // resolve prototypes of extended classes let resolver = this.resolver; for (let i = 0, k = queuedExtends.length; i < k; ++i) { let thisPrototype = queuedExtends[i]; + assert(thisPrototype.kind == ElementKind.ClassPrototype); let extendsNode = assert(thisPrototype.extendsNode); // must be present if in queuedExtends let baseElement = resolver.resolveTypeName(extendsNode.name, thisPrototype.parent); if (!baseElement) continue; - if (thisPrototype.kind == ElementKind.ClassPrototype) { - if (baseElement.kind == ElementKind.ClassPrototype) { - let basePrototype = baseElement; - if (basePrototype.hasDecorator(DecoratorFlags.Final)) { - this.error( - DiagnosticCode.Class_0_is_final_and_cannot_be_extended, - extendsNode.range, basePrototype.identifierNode.text - ); - } - if ( - basePrototype.hasDecorator(DecoratorFlags.Unmanaged) != - thisPrototype.hasDecorator(DecoratorFlags.Unmanaged) - ) { - this.error( - DiagnosticCode.Unmanaged_classes_cannot_extend_managed_classes_and_vice_versa, - Range.join(thisPrototype.identifierNode.range, extendsNode.range) - ); - } - if (!thisPrototype.extends(basePrototype)) { - thisPrototype.basePrototype = basePrototype; - } else { - this.error( - DiagnosticCode._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, - basePrototype.identifierNode.range, - basePrototype.identifierNode.text, - ); - } - } else { + if (baseElement.kind == ElementKind.ClassPrototype) { + let basePrototype = baseElement; + if (basePrototype.hasDecorator(DecoratorFlags.Final)) { this.error( - DiagnosticCode.A_class_may_only_extend_another_class, - extendsNode.range + DiagnosticCode.Class_0_is_final_and_cannot_be_extended, + extendsNode.range, basePrototype.identifierNode.text ); } - } else if (thisPrototype.kind == ElementKind.InterfacePrototype) { - if (baseElement.kind == ElementKind.InterfacePrototype) { - const basePrototype = baseElement; - if (!thisPrototype.extends(basePrototype)) { - thisPrototype.basePrototype = basePrototype; - } else { - this.error( - DiagnosticCode._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, - basePrototype.identifierNode.range, - basePrototype.identifierNode.text, - ); - } + if ( + basePrototype.hasDecorator(DecoratorFlags.Unmanaged) != + thisPrototype.hasDecorator(DecoratorFlags.Unmanaged) + ) { + this.error( + DiagnosticCode.Unmanaged_classes_cannot_extend_managed_classes_and_vice_versa, + Range.join(thisPrototype.identifierNode.range, extendsNode.range) + ); + } + if (!thisPrototype.extends(basePrototype)) { + thisPrototype.basePrototype = basePrototype; } else { this.error( - DiagnosticCode.An_interface_can_only_extend_an_interface, - extendsNode.range + DiagnosticCode._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, + basePrototype.identifierNode.range, + basePrototype.identifierNode.text, ); } + } else { + this.error( + DiagnosticCode.A_class_may_only_extend_another_class, + extendsNode.range + ); } } @@ -1398,7 +1379,7 @@ export class Program extends DiagnosticEmitter { } } - // resolve prototypes of implemented interfaces + // resolve prototypes of implemented/extended interfaces for (let i = 0, k = queuedImplements.length; i < k; ++i) { let thisPrototype = queuedImplements[i]; let implementsNodes = assert(thisPrototype.implementsNodes); // must be present if in queuedImplements @@ -1410,10 +1391,23 @@ export class Program extends DiagnosticEmitter { let interfacePrototype = interfaceElement; let interfacePrototypes = thisPrototype.interfacePrototypes; if (!interfacePrototypes) thisPrototype.interfacePrototypes = interfacePrototypes = new Array(); - interfacePrototypes.push(interfacePrototype); + if ( + thisPrototype.kind == ElementKind.Interface && + thisPrototype.implements(interfacePrototype) + ) { + this.error( + DiagnosticCode._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, + interfacePrototype.identifierNode.range, + interfacePrototype.identifierNode.text, + ); + } else { + interfacePrototypes.push(interfacePrototype); + } } else { this.error( - DiagnosticCode.A_class_can_only_implement_an_interface, + thisPrototype.kind == ElementKind.InterfacePrototype + ? DiagnosticCode.An_interface_can_only_extend_an_interface + : DiagnosticCode.A_class_can_only_implement_an_interface, implementsNode.range ); } @@ -2473,7 +2467,7 @@ export class Program extends DiagnosticEmitter { break; } case NodeKind.InterfaceDeclaration: { - element = this.initializeInterface(declaration, parent, queuedExtends); + element = this.initializeInterface(declaration, parent, queuedImplements); break; } case NodeKind.NamespaceDeclaration: { @@ -2624,7 +2618,7 @@ export class Program extends DiagnosticEmitter { /** Parent element, usually a file or namespace. */ parent: Element, /** So far queued `extends` clauses. */ - queuedExtends: ClassPrototype[], + queuedImplements: ClassPrototype[], ): InterfacePrototype | null { let name = declaration.name.text; let element = new InterfacePrototype( @@ -2637,8 +2631,10 @@ export class Program extends DiagnosticEmitter { ); if (!parent.add(name, element)) return null; - // remember interfaces that extend another interface - if (declaration.extendsType) queuedExtends.push(element); + // remember interfaces that extend other interfaces + // Note: See the corresponding note in parseClassOrInterface (in parser.ts) for + // further information as to why implementsTypes is used. + if (declaration.implementsTypes) queuedImplements.push(element); let memberDeclarations = declaration.members; for (let i = 0, k = memberDeclarations.length; i < k; ++i) { @@ -2757,7 +2753,7 @@ export class Program extends DiagnosticEmitter { break; } case NodeKind.InterfaceDeclaration: { - this.initializeInterface(member, original, queuedExtends); + this.initializeInterface(member, original, queuedImplements); break; } case NodeKind.NamespaceDeclaration: { @@ -4270,6 +4266,24 @@ export class ClassPrototype extends DeclaredElement { return false; } + implements(other: InterfacePrototype, seen: Set | null = null): bool { + if (this.interfacePrototypes) { + if (!seen) seen = new Set(); + let interfacePrototypes = assert(this.interfacePrototypes); + + for (let i = 0, k = interfacePrototypes.length; i < k; ++i) { + let prototype = unchecked(interfacePrototypes[i]); + + if (prototype == other) return true; + if (seen.has(prototype)) continue; + seen.add(prototype); + + if (prototype.implements(other, seen)) return true; + } + } + return false; + } + /** Adds an element as an instance member of this one. Returns the previous element if a duplicate. */ addInstance(name: string, element: DeclaredElement): bool { let originalDeclaration = element.declaration; @@ -4529,9 +4543,11 @@ export class Class extends TypedElement { // Start with the interface itself, adding this class and its extenders to // its implementers. Repeat for the interface's bases that are indirectly // implemented by means of being extended by the interface. - let nextIface: Interface | null = iface; + // TODO: Maybe add a fast path when `iface` has no bases? + let ifaceStack = [iface]; let extenders = this.extenders; do { + let nextIface = assert(ifaceStack.pop()); let implementers = nextIface.implementers; if (!implementers) nextIface.implementers = implementers = new Set(); implementers.add(this); @@ -4541,8 +4557,19 @@ export class Class extends TypedElement { implementers.add(extender); } } - nextIface = nextIface.base; - } while (nextIface); + + let nextIfaces = nextIface.interfaces; + if (!nextIfaces) continue; + + let stackIndex = ifaceStack.length; + + // Calls the internal ensureCapacity() when run in the bootstrapped compiler: + ifaceStack.length = stackIndex + nextIfaces.size; + + for (let _values = Set_values(nextIfaces), i = 0, k = _values.length; i < k; ++i) { + ifaceStack[stackIndex++] = unchecked(_values[i]); + } + } while (ifaceStack.length); } /** Adds an interface. */ @@ -4561,7 +4588,7 @@ export class Class extends TypedElement { if (target.isInterface) { if (this.isInterface) { // targetInterface = thisInterface - return this == target || this.extends(target); + return this == target || this.implements(target); } else { // targetInterface = thisClass return this.implements(target); @@ -4835,7 +4862,7 @@ export class Class extends TypedElement { return true; } - /** Tests if this class or interface extends the given class or interface. */ + /** Tests if this class extends the given class. */ extends(other: Class): bool { return other.hasExtender(this); } diff --git a/tests/compiler/instanceof.debug.wat b/tests/compiler/instanceof.debug.wat index a0d0a1b0aa..e76565d8d6 100644 --- a/tests/compiler/instanceof.debug.wat +++ b/tests/compiler/instanceof.debug.wat @@ -4235,11 +4235,11 @@ i32.load $0 local.set $1 local.get $1 - i32.const 13 + i32.const 14 i32.eq br_if $is_instance local.get $1 - i32.const 14 + i32.const 13 i32.eq br_if $is_instance i32.const 0 @@ -4290,15 +4290,15 @@ i32.load $0 local.set $1 local.get $1 - i32.const 16 + i32.const 19 i32.eq br_if $is_instance local.get $1 - i32.const 19 + i32.const 22 i32.eq br_if $is_instance local.get $1 - i32.const 22 + i32.const 16 i32.eq br_if $is_instance i32.const 0 @@ -4315,11 +4315,11 @@ i32.load $0 local.set $1 local.get $1 - i32.const 19 + i32.const 22 i32.eq br_if $is_instance local.get $1 - i32.const 22 + i32.const 19 i32.eq br_if $is_instance i32.const 0 diff --git a/tests/compiler/instanceof.release.wat b/tests/compiler/instanceof.release.wat index e5507b780a..06b572b400 100644 --- a/tests/compiler/instanceof.release.wat +++ b/tests/compiler/instanceof.release.wat @@ -1559,11 +1559,11 @@ i32.sub i32.load $0 local.tee $0 - i32.const 19 + i32.const 22 i32.eq br_if $is_instance local.get $0 - i32.const 22 + i32.const 19 i32.eq br_if $is_instance i32.const 0 @@ -1637,7 +1637,7 @@ i32.add global.set $~lib/memory/__stack_pointer ) - (func $instanceof/assertDynamicFalse (param $0 i32) + (func $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> (param $0 i32) (local $1 i32) global.get $~lib/memory/__stack_pointer i32.const 4 @@ -1663,7 +1663,7 @@ i32.store $0 local.get $0 if (result i32) - block $__inlined_func$~instanceof|instanceof/Y (result i32) + block $__inlined_func$~instanceof|instanceof/IC (result i32) block $is_instance local.get $0 i32.const 8 @@ -1678,17 +1678,18 @@ i32.eq br_if $is_instance i32.const 0 - br $__inlined_func$~instanceof|instanceof/Y + br $__inlined_func$~instanceof|instanceof/IC end i32.const 1 end else i32.const 0 end + i32.eqz if i32.const 0 i32.const 1456 - i32.const 19 + i32.const 12 i32.const 5 call $~lib/builtins/abort unreachable @@ -1746,6 +1747,67 @@ i32.add global.set $~lib/memory/__stack_pointer ) + (func $instanceof/assertDynamicFalse (param $0 i32) + (local $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1588 + i32.lt_s + if + i32.const 34384 + i32.const 34432 + i32.const 1 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + local.tee $1 + i32.const 0 + i32.store $0 + local.get $1 + local.get $0 + i32.store $0 + local.get $0 + if (result i32) + block $__inlined_func$~instanceof|instanceof/IC (result i32) + block $is_instance + local.get $0 + i32.const 8 + i32.sub + i32.load $0 + local.tee $0 + i32.const 19 + i32.eq + br_if $is_instance + local.get $0 + i32.const 22 + i32.eq + br_if $is_instance + i32.const 0 + br $__inlined_func$~instanceof|instanceof/IC + end + i32.const 1 + end + else + i32.const 0 + end + if + i32.const 0 + i32.const 1456 + i32.const 19 + i32.const 5 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + ) (func $~lib/rt/__visit_members (param $0 i32) block $invalid block $instanceof/IE @@ -2496,11 +2558,11 @@ i32.sub i32.load $0 local.tee $0 - i32.const 13 + i32.const 14 i32.eq br_if $is_instance2 local.get $0 - i32.const 14 + i32.const 13 i32.eq br_if $is_instance2 i32.const 0 @@ -2555,11 +2617,11 @@ i32.sub i32.load $0 local.tee $0 - i32.const 13 + i32.const 14 i32.eq br_if $is_instance4 local.get $0 - i32.const 14 + i32.const 13 i32.eq br_if $is_instance4 i32.const 0 @@ -2615,11 +2677,11 @@ i32.sub i32.load $0 local.tee $0 - i32.const 13 + i32.const 14 i32.eq br_if $is_instance6 local.get $0 - i32.const 14 + i32.const 13 i32.eq br_if $is_instance6 i32.const 0 @@ -2694,11 +2756,11 @@ i32.sub i32.load $0 local.tee $0 - i32.const 13 + i32.const 14 i32.eq br_if $is_instance8 local.get $0 - i32.const 14 + i32.const 13 i32.eq br_if $is_instance8 i32.const 0 @@ -2763,11 +2825,11 @@ i32.sub i32.load $0 local.tee $0 - i32.const 13 + i32.const 14 i32.eq br_if $is_instance10 local.get $0 - i32.const 14 + i32.const 13 i32.eq br_if $is_instance10 i32.const 0 @@ -2833,11 +2895,11 @@ i32.sub i32.load $0 local.tee $0 - i32.const 13 + i32.const 14 i32.eq br_if $is_instance12 local.get $0 - i32.const 14 + i32.const 13 i32.eq br_if $is_instance12 i32.const 0 @@ -3123,13 +3185,13 @@ local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/y local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/z local.tee $0 @@ -3147,13 +3209,13 @@ local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/z local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/w local.tee $0 @@ -3183,8 +3245,57 @@ global.get $instanceof/x local.tee $0 i32.store $0 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 1588 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + local.tee $1 + i32.const 0 + i32.store $0 + local.get $1 local.get $0 - call $instanceof/assertDynamicFalse + i32.store $0 + local.get $0 + if (result i32) + block $__inlined_func$~instanceof|instanceof/Y (result i32) + block $is_instance21 + local.get $0 + i32.const 8 + i32.sub + i32.load $0 + local.tee $0 + i32.const 22 + i32.eq + br_if $is_instance21 + local.get $0 + i32.const 19 + i32.eq + br_if $is_instance21 + i32.const 0 + br $__inlined_func$~instanceof|instanceof/Y + end + i32.const 1 + end + else + i32.const 0 + end + if + i32.const 0 + i32.const 1456 + i32.const 19 + i32.const 5 + call $~lib/builtins/abort + unreachable + end + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer global.get $instanceof/x local.tee $0 @@ -3193,10 +3304,10 @@ call $instanceof/assertDynamicFalse global.get $~lib/memory/__stack_pointer global.get $instanceof/y + local.tee $0 i32.store $0 global.get $~lib/memory/__stack_pointer - global.get $instanceof/y - local.tee $0 + local.get $0 i32.store $0 local.get $0 call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> @@ -3208,10 +3319,10 @@ call $instanceof/assertDynamicFalse global.get $~lib/memory/__stack_pointer global.get $instanceof/z + local.tee $0 i32.store $0 global.get $~lib/memory/__stack_pointer - global.get $instanceof/z - local.tee $0 + local.get $0 i32.store $0 local.get $0 call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> @@ -3259,25 +3370,25 @@ local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicFalse + call $instanceof/assertDynamicFalse global.get $~lib/memory/__stack_pointer global.get $instanceof/x local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicFalse + call $instanceof/assertDynamicFalse global.get $~lib/memory/__stack_pointer global.get $instanceof/x local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicFalse + call $instanceof/assertDynamicFalse global.get $~lib/memory/__stack_pointer global.get $instanceof/x local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicFalse + call $instanceof/assertDynamicFalse global.get $~lib/memory/__stack_pointer global.get $instanceof/x i32.store $0 @@ -3289,25 +3400,25 @@ local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/y local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/y local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/y local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/y i32.store $0 @@ -3319,25 +3430,25 @@ local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/z local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/z local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/z local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/z i32.store $0 @@ -3355,13 +3466,13 @@ local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicFalse + call $instanceof/assertDynamicFalse global.get $~lib/memory/__stack_pointer global.get $instanceof/x local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicFalse + call $instanceof/assertDynamicFalse global.get $~lib/memory/__stack_pointer global.get $instanceof/x i32.store $0 @@ -3376,13 +3487,13 @@ local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/y local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/y i32.store $0 @@ -3397,13 +3508,13 @@ local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/z local.tee $0 i32.store $0 local.get $0 - call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/Y> + call $instanceof/assertDynamicTrue<~lib/object/Object,instanceof/IC> global.get $~lib/memory/__stack_pointer global.get $instanceof/z i32.store $0