Constant vtables for object-literal methods, skipping the per-cast heap patch#254
Merged
Merged
Conversation
…nd add regression test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
docs/interface-vtable-simplification-design.md(follow-up to Heap-allocate patched interface vtable so it survives in a global __cctor #251/Fix cross-module interface field/method vtable index mismatch #252): an object-literal method's field value is a compile-time-known function symbol (FlatSymbolRefAttr) regardless of whether it captures variables - captures land in a separate.captureddata field the function reads viathis, not a different function per instance.objectLiteralMethodSymbolsMap(keyed on the object literal's ownObjectStorageType, populated inaddObjectFuncFieldInfo) letsmlirGenObjectVirtualTableDefinitionForInterfaceemit a constantSymbolRefOpfor a method slot instead of the GEP-on-null offset placeholder that previously requiredmlirGenCreateInterfaceVTableForObjectto heap-clone and runtime-patch the vtable on every cast. When every interface method resolves this way, the clone+patch is skipped entirely - same footing as a method-less interface. The runtime patch remains as a fallback for methods whosefuncNameisn't known locally (an object type reconstructed from a@dllimportdeclaration).hash_value(objectType)), but a method field'sFunctionTypeembeds the literal's ownObjectStorageTypesymbol (source location) as itsthisparameter, so "same shape" never actually holds once the method's own signature is counted - confirmed against a compiled counterexample before relying on it.InterfaceInfo::methods), not merely "is this vtable slot func-typed".interface Something { toString: () => string; }categorizestoStringas an interface field (PropertySignaturewith a function type), not a method - the access site (InterfaceFieldAccess, offset semantics) is different from a realMethodSignature's (InterfaceMethodAccess, raw function-pointer slot). The first version of this change substituted a constant symbol into any func-typed slot, handing a raw pointer to code that computesthisVal + slotValueexpecting an offset - a garbage call target, crash confirmed via a WinDbg dump (call qword ptr [rax+rdx], both registers built from the garbage sum).Test plan
00interface_function_typed_field.ts(thePropertySignature-with-function-type vsMethodSignaturedistinction), both AOT and JIT--emit=mlirspot checks: real methods (00interface_global_method.ts) now bake ats.SymbolRefinto the vtable global with no heapts.Newfor the vtable clone; function-typed fields (00interface_object.ts) still correctly use the GEP-on-null offset schemectest -C Debug- 718/718 passed, no regressions🤖 Generated with Claude Code