11"""Core data structures for compiled code templates."""
22
3+ import copy
34import dataclasses
45import enum
56import sys
@@ -148,6 +149,9 @@ class HoleValue(enum.Enum):
148149 "IMAGE_REL_AMD64_REL32" ,
149150}
150151
152+ _CROSS_SECTION_PREFIX = "_JIT_CROSS_SECTION_"
153+ _CROSS_SECTION_SUFFIX = "_JIT_CROSS_SECTION"
154+
151155@dataclasses .dataclass
152156class Hole :
153157 """
@@ -170,8 +174,16 @@ class Hole:
170174 func : str = dataclasses .field (init = False )
171175 offset2 : int = - 1
172176 void : bool = False
173- # Convenience method:
174- replace = dataclasses .replace
177+
178+ def replace (self , ** changes : typing .Any ) -> typing .Self :
179+ field_names = {field .name for field in dataclasses .fields (self )}
180+ for name in changes :
181+ if name not in field_names :
182+ raise TypeError (f"unexpected field name: { name !r} " )
183+ result = copy .copy (self )
184+ for name , value in changes .items ():
185+ setattr (result , name , value )
186+ return result
175187
176188 def __post_init__ (self ) -> None :
177189 self .func = _PATCH_FUNCS [self .kind ]
@@ -295,6 +307,9 @@ def convert_labels_to_relocations(self) -> None:
295307 first = first_in_pair [index ]
296308 hole .fold (first )
297309
310+ self .split_code_at_cold_start ()
311+
312+ def split_code_at_cold_start (self ) -> None :
298313 cold_start = self .symbols .get ("_JIT_COLD_START" )
299314 if cold_start is None :
300315 return
@@ -330,6 +345,8 @@ def process_relocations(self, known_symbols: dict[str, int]) -> None:
330345 """Fix up all GOT and internal relocations for this stencil group."""
331346 for stencil in self ._code_stencils ():
332347 for hole in stencil .holes .copy ():
348+ if self ._resolve_cross_section_symbol (hole ):
349+ continue
333350 if (
334351 hole .kind
335352 in {"R_AARCH64_CALL26" , "R_AARCH64_JUMP26" , "ARM64_RELOC_BRANCH26" }
@@ -379,6 +396,8 @@ def process_relocations(self, known_symbols: dict[str, int]) -> None:
379396 self .data .pad (8 )
380397 for stencil in self ._all_stencils ():
381398 for hole in stencil .holes :
399+ if self ._resolve_cross_section_symbol (hole ):
400+ continue
382401 if hole .value is HoleValue .GOT :
383402 assert hole .symbol is not None
384403 if "_JIT_" in hole .symbol :
@@ -415,6 +434,29 @@ def process_relocations(self, known_symbols: dict[str, int]) -> None:
415434 self .cold_code .holes .sort (key = lambda hole : hole .offset )
416435 self .data .holes .sort (key = lambda hole : hole .offset )
417436
437+ def _resolve_cross_section_symbol (self , hole : Hole ) -> bool :
438+ if hole .value is not HoleValue .ZERO or hole .symbol is None :
439+ return False
440+ symbol = hole .symbol
441+ if not (
442+ symbol .startswith (_CROSS_SECTION_PREFIX )
443+ and symbol .endswith (_CROSS_SECTION_SUFFIX )
444+ ):
445+ return False
446+ target = symbol .removeprefix (_CROSS_SECTION_PREFIX ).removesuffix (
447+ _CROSS_SECTION_SUFFIX
448+ )
449+ try :
450+ value , addend = self .symbols [target ]
451+ except KeyError :
452+ raise ValueError (
453+ f"Missing cross-section relocation target { target } "
454+ ) from None
455+ hole .value = value
456+ hole .addend += addend
457+ hole .symbol = None
458+ return True
459+
418460 def _jit_symbol_table_lookup (self , symbol : str ) -> int :
419461 return len (self .data .body ) + self ._jit_symbol_table .setdefault (
420462 symbol , 8 * len (self ._jit_symbol_table )
0 commit comments