#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include "slate.h"
#include "file.h"
#include "directory.h"
#include "extprim.h"

/*** Prototypes ***/

struct Object;
struct RoleTable;
struct SlotTable;
struct ObjectHeader;
struct MethodCacheEntry;
struct ByteArray;
struct ObjectHeap;
struct CompiledMethod;
struct LexicalContext;
struct OopArray;
struct Closure;
struct SlotEntry;
struct ObjectPayload;
struct Map;
struct Root;
struct PrimitiveMethod;
struct RoleEntry;
struct Interpreter;
struct ForwardedObject;
struct BreakEntry;
struct Symbol;
struct MethodDefinition;
typedef unsigned long int Word;
struct ObjectHeader
{
  unsigned long int isMarked:1;
  unsigned long int idHash:23;
  unsigned long int objectSize:6;
  unsigned long int objectFormat:2;
};
typedef unsigned long int Bool;
typedef unsigned char Byte;
struct Closure
{
  struct ObjectHeader header;
  struct Map * map;
  struct CompiledMethod * method;
  struct LexicalContext * lexicalWindow[0];
};
struct ObjectPayload
{
  unsigned long int payloadSize:30;
  unsigned long int payloadFormat:2;
};
struct Root
{
  struct ObjectHeader header;
  struct Map * map;
};
struct ForwardedObject
{
  struct ObjectHeader header;
  struct Object * target;
};
struct BreakEntry
{
  unsigned long int oldAddress;
  unsigned long int newAddress;
};
typedef Word ObjectPointer;
struct Object
{
  struct ObjectHeader header;
  struct Map * map;
};
struct MethodCacheEntry
{
  struct MethodDefinition * method;
  ObjectPointer selector;
  struct Map * maps[3];
};
struct ByteArray
{
  struct ObjectHeader header;
  struct Map * map;
  Byte elements[0];
};
struct ObjectHeap
{
  ObjectPointer * rootStack[16];
  unsigned long int rootStackPosition;
  struct Object * markStack[4096];
  unsigned long int markStackPosition;
  Bool markStackOverflow;
  unsigned long int markColor;
  unsigned long int * pinnedCards;
  unsigned long int * stackBottom;
  struct BreakEntry breakTable[512];
  unsigned long int breakTableSize;
  unsigned long int totalAllocated;
  unsigned long int lastAllocated;
  unsigned long int nextLive;
  unsigned long int * memory;
  unsigned long int memoryEnd;
  unsigned long int memoryLimit;
  unsigned long int totalObjectCount;
  unsigned long int lowSpaceThreshold;
  unsigned long int shrinkThreshold;
  unsigned long int growthHeadroom;
  unsigned long int lastHash;
  ObjectPointer TrueObject;
  ObjectPointer FalseObject;
  ObjectPointer NilObject;
  ObjectPointer ClosureWindow;
  ObjectPointer CompiledMethodWindow;
  ObjectPointer PrimitiveMethodWindow;
  ObjectPointer specialObjectsOop;
};
struct CompiledMethod
{
  struct ObjectHeader header;
  struct Map * map;
  struct CompiledMethod * method;
  ObjectPointer selector;
  ObjectPointer inputVariables;
  ObjectPointer localVariables;
  ObjectPointer restVariable;
  struct OopArray * optionalKeywords;
  ObjectPointer heapAllocate;
  ObjectPointer environment;
  struct OopArray * literals;
  struct OopArray * selectors;
  struct ByteArray * code;
  ObjectPointer sourceTree;
  ObjectPointer debugMap;
};
struct LexicalContext
{
  struct ObjectHeader header;
  struct Map * map;
  ObjectPointer framePointer;
  ObjectPointer variables[0];
};
struct OopArray
{
  struct ObjectHeader header;
  struct Map * map;
  ObjectPointer elements[0];
};
struct SlotEntry
{
  ObjectPointer name;
  ObjectPointer offset;
};
struct Map
{
  struct ObjectHeader header;
  struct Map * map;
  ObjectPointer flags;
  ObjectPointer representative;
  struct OopArray * delegates;
  ObjectPointer slotCount;
  struct SlotTable * slotTable;
  struct RoleTable * roleTable;
  unsigned long long int dispatchID;
  unsigned long int visitedPositions;
};
struct PrimitiveMethod
{
  struct ObjectHeader header;
  struct Map * map;
  ObjectPointer index;
  ObjectPointer selector;
  ObjectPointer inputVariables;
};
struct RoleEntry
{
  ObjectPointer name;
  ObjectPointer rolePositions;
  struct MethodDefinition * methodDefinition;
  ObjectPointer nextRole;
};
struct Interpreter
{
  struct ObjectHeader header;
  struct Map * map;
  struct OopArray * stack;
  struct CompiledMethod * method;
  struct Closure * closure;
  struct LexicalContext * lexicalContext;
  ObjectPointer ensureHandlers;
  unsigned long int framePointer;
  unsigned long int codePointer;
  unsigned long int codeSize;
  unsigned long int stackPointer;
  unsigned long int stackSize;
};
struct Symbol
{
  struct ObjectHeader header;
  struct Map * map;
  ObjectPointer cacheMask;
  Byte elements[0];
};
struct MethodDefinition
{
  struct ObjectHeader header;
  struct Map * map;
  ObjectPointer method;
  ObjectPointer slotAccessor;
  unsigned long long int dispatchID;
  unsigned long int dispatchPositions;
  unsigned long int foundPositions;
  unsigned long int dispatchRank;
};
struct RoleTable
{
  struct ObjectHeader header;
  struct Map * map;
  struct RoleEntry roles[0];
};
struct SlotTable
{
  struct ObjectHeader header;
  struct Map * map;
  struct SlotEntry slots[0];
};
static Bool signedLongInt_fitsSmallInt(signed long int i);
static Bool ObjectPointer_isSmallInt(ObjectPointer oop);
static Bool ObjectPointer_isObject(ObjectPointer oop);
static struct Object * ObjectPointer_pointer(ObjectPointer oop);
static ObjectPointer PSObject_asObject(struct Object * p);
static ObjectPointer PSMap_asObject(struct Map * p);
static ObjectPointer unsignedLongInt_asObject(unsigned long int i);
static ObjectPointer signedLongInt_asObject(signed long int i);
static signed long int ObjectPointer_asSmallInt(ObjectPointer oop);
void PSObjectHeap_initializeCollector(struct ObjectHeap * oh);
void PSObjectHeap_initializeWithFirstFreeAt_(struct ObjectHeap * oh, unsigned long int firstFree);
static Bool PSObjectHeap_hasMarked_(struct ObjectHeap * oh, struct Object * obj);
static void PSObjectHeap_mark_(struct ObjectHeap * oh, struct Object * obj);
static void PSObjectHeap_unmark_(struct ObjectHeap * oh, struct Object * obj);
static void PSObjectHeap_markStackPush_(struct ObjectHeap * oh, struct Object * obj);
static struct Object * PSObjectHeap_markStackPop(struct ObjectHeap * oh);
void PSObjectHeap_markAndPushSlotsOf_(struct ObjectHeap * oh, struct Object * obj);
void PSObjectHeap_markAndTrace(struct ObjectHeap * oh);
void PSObjectHeap_markAndPushRoots(struct ObjectHeap * oh);
static void PSObjectHeap_rootStackPush_(struct ObjectHeap * oh, ObjectPointer * root);
static void PSObjectHeap_rootStackPop_(struct ObjectHeap * oh, unsigned long int n);
Bool PSObjectHeap_needsToMark_(struct ObjectHeap * oh, struct Object * obj);
Bool PSObjectHeap_recoverMarkStack(struct ObjectHeap * oh);
static struct Object * PSObjectHeap_makeFreeHoleAt_sized_(struct ObjectHeap * oh, unsigned long int address, unsigned long int size);
static unsigned long int PSObjectHeap_allocationLimit(struct ObjectHeap * oh);
static void PSObjectHeap_makeFreeHole(struct ObjectHeap * oh);
void PSObjectHeap_findNextFree(struct ObjectHeap * oh);
void PSObjectHeap_findNextLive(struct ObjectHeap * oh);
extern void PSObjectHeap_sweep(struct ObjectHeap * oh);
extern void PSObjectHeap_garbageCollect(struct ObjectHeap * oh);
void PSObjectHeap_clearCards(struct ObjectHeap * oh);
void PSObjectHeap_pinCards(struct ObjectHeap * oh);
static Bool PSObjectHeap_isPinned_(struct ObjectHeap * oh, unsigned long int oop);
ObjectPointer PSObjectHeap_remapOop_(struct ObjectHeap * oh, ObjectPointer oop);
void PSObjectHeap_remapOops(struct ObjectHeap * oh);
extern void PSObjectHeap_compact_(struct ObjectHeap * oh, Bool mostlyCompact);
extern struct ForwardedObject * PSObjectHeap_forward_to_(struct ObjectHeap * oh, struct Object * old, struct Object * new);
extern void PSObjectHeap_findHoleSized_(struct ObjectHeap * oh, unsigned long int size);
extern struct Object * PSObjectHeap_allocateChunkSized_withPayload_(struct ObjectHeap * oh, unsigned long int words, unsigned long int payloadSize);
extern struct Object * PSObjectHeap_allocateChunkSized_(struct ObjectHeap * oh, unsigned long int words);
extern Bool PSObjectHeap_isFree_(struct ObjectHeap * oh, ObjectPointer oop);
extern ObjectPointer PSObjectHeap_firstObject(struct ObjectHeap * h);
extern ObjectPointer PSObjectHeap_objectAfter_(struct ObjectHeap * oh, ObjectPointer oop);
extern ObjectPointer PSObjectHeap_specialAt_(struct ObjectHeap * h, unsigned long int index);
void PSObjectHeap_adjustFieldsOf_by_(struct ObjectHeap * h, ObjectPointer oop, signed long int shiftAmountInBytes);
extern unsigned long int PSObjectHeap_adjustAllOopsBy_(struct ObjectHeap * h, unsigned long int shiftAmountInBytes);
extern void PSObjectHeap_initializeWithShift_(struct ObjectHeap * h, unsigned long int shiftAmountInBytes);
extern unsigned long int PSObjectHeap_memoryStart(struct ObjectHeap * h);
extern Bool PSObjectHeap_includes_(struct ObjectHeap * h, unsigned long int address);
extern void PSObjectHeap_checkValid_(struct ObjectHeap * h, unsigned long int address);
ObjectPointer PSObjectHeap_firstAccessibleObject(struct ObjectHeap * h);
ObjectPointer PSObjectHeap_accessibleObjectAfter_(struct ObjectHeap * h, ObjectPointer oop);
ObjectPointer PSObjectHeap_initialInstanceOfMap_(struct ObjectHeap * h, struct Map * map);
ObjectPointer PSObjectHeap_nextInstanceOfMap_after_(struct ObjectHeap * h, struct Map * map, ObjectPointer oop);
ObjectPointer PSObjectHeap_initialDelegateTo_(struct ObjectHeap * h, ObjectPointer parentOop);
ObjectPointer PSObjectHeap_nextDelegateTo_after_(struct ObjectHeap * h, ObjectPointer parentOop, ObjectPointer oop);
ObjectPointer PSObjectHeap_firstReferringTo_(struct ObjectHeap * h, ObjectPointer targetOop);
ObjectPointer PSObjectHeap_nextReferringTo_after_(struct ObjectHeap * h, ObjectPointer targetOop, ObjectPointer oop);
unsigned long int PSObjectHeap_newIdentityHash(struct ObjectHeap * h);
static unsigned long int PSObjectHeap_memorySize(struct ObjectHeap * h);
extern void PSObjectHeap_growBy_(struct ObjectHeap * h, unsigned long int delta);
extern void PSObjectHeap_shrinkBy_(struct ObjectHeap * h, unsigned long int delta);
static void PWord_copyWords_into_(Word * src, unsigned long int n, Word * dst);
static void PByte_copyBytes_into_(Byte * src, unsigned long int n, Byte * dst);
static void PWord_fillWords_with_(Word * dst, unsigned long int n, Word value);
static void PByte_fillBytes_with_(Byte * dst, unsigned long int n, Byte value);
static unsigned long int PSObject_payloadSize(struct Object * obj);
static unsigned long int PSObject_memoryUsage(struct Object * obj);
static unsigned long int PSObject_wordSize(struct Object * obj);
static unsigned long int PSObject_firstSlotOffset(struct Object * obj);
static unsigned long int PSObject_slotCount(struct Object * obj);
static unsigned long int PSObject_oopCount(struct Object * obj);
static unsigned long int PSObject_lastSlotOffset(struct Object * obj);
static unsigned long int PSObject_lastOopOffset(struct Object * obj);
static unsigned long int PSObject_arrayOffset(struct Object * obj);
static ObjectPointer * PSObject_arrayElements(struct Object * obj);
static unsigned long int PSObject_arraySize(struct Object * obj);
static unsigned long int PSObject_totalSize(struct Object * obj);
static unsigned long int PSObject_byteSize(struct Object * obj);
static ObjectPointer * PSObject_slotValues(struct Object * obj);
static ObjectPointer PSObject_slotValueAt_(struct Object * obj, unsigned long int index);
static ObjectPointer PSObject_slotValueAt_put_(struct Object * obj, unsigned long int index, unsigned long int oop);
static ObjectPointer PSObject_slotValueAtOffset_(struct Object * obj, unsigned long int offset);
static ObjectPointer PSObject_slotValueAtOffset_put_(struct Object * obj, unsigned long int offset, ObjectPointer value);
static signed long int PSByteArray_extractInto_sized_(struct ByteArray * fromArray, Byte * targetBuffer, unsigned long int bufferSize);
extern struct Object * PSObjectHeap_clone_(struct ObjectHeap * oh, struct Object * obj);
static struct Object * PSObjectHeap_cloneSpecial_(struct ObjectHeap * oh, unsigned long int index);
extern struct Object * PSObjectHeap_cloneOopArray_sized_(struct ObjectHeap * oh, struct Object * proto, unsigned long int oops);
extern struct Object * PSObjectHeap_cloneByteArray_sized_(struct ObjectHeap * oh, struct Object * proto, unsigned long int bytes);
static struct Object * PSObjectHeap_newOopArray_sized_(struct ObjectHeap * oh, unsigned long int index, unsigned long int oops);
static struct Object * PSObjectHeap_newByteArray_sized_(struct ObjectHeap * oh, unsigned long int index, unsigned long int bytes);
static struct Object * PSObjectHeap_newByteArray_from_sized_(struct ObjectHeap * oh, unsigned long int index, Byte * buffer, unsigned long int bytes);
static unsigned long int PSRoleTable_capacity(struct RoleTable * roles);
unsigned long int PSRoleTable_emptySpace(struct RoleTable * roles);
unsigned long int PSRoleTable_minimumCapacityAccommodating_(struct RoleTable * roles, signed long int n);
struct RoleEntry * PSRoleTable_hashEntryForName_(struct RoleTable * roles, ObjectPointer name);
struct RoleEntry * PSRoleTable_hashEntryForInsertingName_(struct RoleTable * roles, ObjectPointer name);
struct RoleTable * PSRoleTable_growBy_excluding_(struct RoleTable * roles, signed long int n, struct MethodDefinition * method);
static unsigned long int PSSlotTable_capacity(struct SlotTable * slots);
unsigned long int PSSlotTable_emptySpace(struct SlotTable * slots);
extern struct SlotEntry * PSSlotTable_hashEntryForName_(struct SlotTable * slots, ObjectPointer name);
struct SlotEntry * PSSlotTable_hashEntryForInsertingName_(struct SlotTable * slots, ObjectPointer name);
unsigned long int PSSlotTable_minimumCapacityAccommodating_(struct SlotTable * slots, signed long int n);
struct SlotTable * PSSlotTable_growBy_excluding_(struct SlotTable * slots, signed long int n, ObjectPointer name);
void PSSlotTable_relocateAll_above_by_(struct SlotTable * slots, unsigned long int type, unsigned long int offset, signed long int amount);
static struct Map * PSObjectHeap_cloneMap_(struct ObjectHeap * h, struct Map * map);
static struct Map * PSObject_changeMapTo_(struct Object * obj, struct Map * map);
static struct Map * PSObject_makeRepresentativeOf_(struct Object * obj, struct Map * map);
struct Object * PSObject_addSlotNamed_valued_at_(struct Object * obj, ObjectPointer name, ObjectPointer value, unsigned long int offset);
extern struct Object * PSObject_addSlotNamed_valued_(struct Object * obj, ObjectPointer name, ObjectPointer value);
struct Object * PSObject_addDelegateNamed_valued_at_(struct Object * obj, ObjectPointer name, ObjectPointer value, unsigned long int offset);
extern struct Object * PSObject_addDelegateNamed_valued_(struct Object * obj, ObjectPointer name, ObjectPointer value);
extern struct Object * PSObject_addDelegateNamed_before_valued_(struct Object * obj, ObjectPointer name, ObjectPointer succ, ObjectPointer value);
extern struct Object * PSObject_addDelegateNamed_after_valued_(struct Object * obj, ObjectPointer name, ObjectPointer pred, ObjectPointer value);
extern struct Object * PSObject_removeSlotNamed_(struct Object * obj, ObjectPointer name);
struct Object * PSObject_removeSlot_(struct Object * obj, struct SlotEntry * entry);
struct Object * PSObject_removeDelegate_(struct Object * obj, struct SlotEntry * entry);
extern Bool PSObject_addRoleNamed_at_dispatching_(struct Object * obj, ObjectPointer name, unsigned long int position, struct MethodDefinition * method);
extern Bool PSObject_removeRoleNamed_dispatching_(struct Object * obj, ObjectPointer name, struct MethodDefinition * method);
extern struct MethodDefinition * PSObject_hasRoleNamed_at_dispatching_(struct Object * obj, unsigned long int selector, unsigned long int positions, ObjectPointer method);
extern struct MethodDefinition * ObjectPointer_isMethod_on_arity_(ObjectPointer method, ObjectPointer selector, ObjectPointer * args, unsigned long int n);
extern struct MethodDefinition * ObjectPointer_asMethod_on_arity_(ObjectPointer method, ObjectPointer selector, ObjectPointer * args, unsigned long int n);
extern void ObjectPointer_flushMethodCache(ObjectPointer selector);
static struct Map * ObjectPointer_checkMap(ObjectPointer arg);
void PSMethodDefinition_cacheAs_on_arity_(struct MethodDefinition * def, ObjectPointer name, ObjectPointer * arguments, unsigned long int n);
static struct MethodDefinition * ObjectPointer_checkMethodCacheOn_(ObjectPointer name, ObjectPointer * arguments);
extern struct MethodDefinition * ObjectPointer_dispatchTo_arity_above_(ObjectPointer name, ObjectPointer * arguments, unsigned long int n, ObjectPointer resendMethod);
extern void PSInterpreter_growStack(struct Interpreter * i);
static void PSInterpreter_stackPush_(struct Interpreter * i, ObjectPointer oop);
static void PSInterpreter_stackAllocate_(struct Interpreter * i, unsigned long int n);
static ObjectPointer PSInterpreter_stackPop(struct Interpreter * i);
static signed long int PSInterpreter_decodeShort(struct Interpreter * i);
static unsigned long int PSInterpreter_decodeImmediate(struct Interpreter * i);
extern void PSInterpreter_signal_on_arity_withOptionals_(struct Interpreter * i, unsigned long int signalIndex, ObjectPointer * args, unsigned long int n, struct OopArray * opts);
extern void PSInterpreter_signal_with_(struct Interpreter * i, unsigned long int signalIndex, ObjectPointer x);
extern void PSInterpreter_signal_with_with_(struct Interpreter * i, unsigned long int signalIndex, ObjectPointer x, ObjectPointer y);
extern void PSInterpreter_signal_with_with_with_(struct Interpreter * i, unsigned long int signalIndex, ObjectPointer x, ObjectPointer y, ObjectPointer z);
static void PSInterpreter_sendMessage_withOptionals_(struct Interpreter * i, unsigned long int n, struct OopArray * opts);
static void PSInterpreter_sendMessageWithOptionals_(struct Interpreter * i, unsigned long int n);
extern void PSInterpreter_dispatchOptionals_(struct Interpreter * i, struct OopArray * opts);
static void PSInterpreter_send_to_arity_withOptionals_(struct Interpreter * i, ObjectPointer selector, ObjectPointer * args, unsigned long int n, struct OopArray * opts);
extern void PSInterpreter_send_to_through_arity_withOptionals_(struct Interpreter * i, ObjectPointer selector, ObjectPointer * args, ObjectPointer * dispatchers, unsigned long int n, struct OopArray * opts);
extern void PSInterpreter_apply_to_arity_withOptionals_(struct Interpreter * i, struct Closure * closure, ObjectPointer * args, unsigned long int n, struct OopArray * opts);
extern void PSInterpreter_resendMessage_(struct Interpreter * i, unsigned long int n);
static Bool PSInterpreter_dispatchOptionalKeyword_valued_(struct Interpreter * i, ObjectPointer key, ObjectPointer value);
static void PSInterpreter_loadVariable_(struct Interpreter * i, unsigned long int n);
static void PSInterpreter_storeVariable_(struct Interpreter * i, unsigned long int n);
static void PSInterpreter_loadFreeVariable_(struct Interpreter * i, unsigned long int n);
static void PSInterpreter_storeFreeVariable_(struct Interpreter * i, unsigned long int n);
static void PSInterpreter_loadLiteral_(struct Interpreter * i, unsigned long int n);
static void PSInterpreter_loadSelector_(struct Interpreter * i, unsigned long int n);
static void PSInterpreter_popStack_(struct Interpreter * i, unsigned long int n);
static void PSInterpreter_newArray_(struct Interpreter * i, unsigned long int n);
static void PSInterpreter_newClosure_(struct Interpreter * i, unsigned long int n);
static void PSInterpreter_pushInteger_(struct Interpreter * i, unsigned long int n);
static void PSInterpreter_jumpTo(struct Interpreter * i);
static void PSInterpreter_branchIfTrue(struct Interpreter * i);
static void PSInterpreter_branchIfFalse(struct Interpreter * i);
static void PSInterpreter_pushEnvironment(struct Interpreter * i);
static void PSInterpreter_pushNil(struct Interpreter * i);
static void PSInterpreter_pushTrue(struct Interpreter * i);
static void PSInterpreter_pushFalse(struct Interpreter * i);
static void PSInterpreter_isIdenticalTo(struct Interpreter * i);
extern Bool PSInterpreter_returnFrom_withResult_(struct Interpreter * i, unsigned long int n, Bool hasResult);
extern void PSInterpreter_branchKeyed_(struct Interpreter * i, unsigned long int n);
extern void PSInterpreter_interpret(struct Interpreter * i);
void _primitive0(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive1(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive2(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive3(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive4(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive5(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive6(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive7(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive8(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive9(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive10(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive11(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive12(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive13(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive14(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive15(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive16(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive17(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive18(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive19(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive20(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive21(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive22(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive23(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive24(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive25(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive26(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive27(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive28(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive29(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive30(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive31(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive32(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive33(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive34(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive35(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive36(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive37(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive38(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive39(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive40(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive41(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive42(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive43(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive44(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive45(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive46(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive47(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive48(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive49(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive50(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive51(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive52(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive53(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive54(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive55(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive56(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive57(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive58(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive59(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive60(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive61(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive62(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive63(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive64(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive65(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive66(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive67(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive68(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive69(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive70(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive71(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive72(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive73(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive74(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive75(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive76(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive77(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive78(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive79(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive80(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive81(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive82(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive83(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive84(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive85(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive86(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive87(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive88(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive89(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive90(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive91(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive92(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive93(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive94(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive95(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive96(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive97(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive98(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive99(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive100(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive101(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);
void _primitive102(struct Interpreter * interpreter, ObjectPointer * arguments, unsigned long int argumentsSize, struct OopArray * optionals);

/*** Constants ***/

const unsigned long int BCJumpTo = 15;
const unsigned long int DelegationStackSize = 256;
const unsigned long int MapProto = 8;
const unsigned long int BCPushInteger = 13;
const unsigned long int MultiplyOverflowSymbol = 28;
const unsigned long int BCReturnFrom = 12;
const unsigned long int SlotTypeBits = 1;
const unsigned long int BCBranchIfTrue = 31;
const unsigned long int WrongInputsToSymbol = 21;
const unsigned long int TrueObject = 3;
const unsigned long int BCNewArray = 8;
const unsigned long int ClosureWindow = 12;
const unsigned long int BCResume = 143;
const unsigned long int NilObject = 2;
const unsigned long int NotABooleanSymbol = 30;
const unsigned long int BCPushTrue = 111;
const unsigned long int FormatOopArray = 1;
const unsigned long int BCStoreFreeVariable = 4;
const unsigned long int ClosureProto = 15;
const unsigned long int ArrayProto = 5;
const Bool True = 1;
const unsigned long int FloatProto = 11;
const unsigned long int SlotTypeDelegate = 1;
const Bool False = 0;
const unsigned long int BCLoadFreeVariable = 3;
const unsigned long int BCPopStack = 7;
const unsigned long int BCBranchIfFalse = 47;
void * const Nil = 0;
const unsigned long int BitShiftOverflowSymbol = 25;
const unsigned long int MethodCacheArity = 3;
const unsigned long int BCPushEnvironment = 63;
const unsigned long int BCIsIdenticalTo = 95;
const unsigned long int MarkColorMask = 1;
const unsigned long int PrimitiveMethodWindow = 14;
const unsigned long int SubtractOverflowSymbol = 27;
const unsigned long int BCPushNil = 79;
const unsigned long int KeyNotFoundSymbol = 24;
const unsigned long int SlotNotFoundSymbol = 23;
const unsigned long int BCLoadLiteral = 5;
const unsigned long int SlotOffsetMask = 4294967294U;
const unsigned long int SlotTypeMask = 1;
const unsigned long int BCBranchKeyed = 10;
const unsigned long int AddOverflowSymbol = 26;
const unsigned long int IdHashForwarded = 8388592;
const unsigned long int RootStackSize = 16;
const unsigned long int SlotTypeData = 0;
const unsigned long int BCPushFalse = 127;
const unsigned long int MayNotReturnToSymbol = 22;
const unsigned long int MarkStackSize = 4096;
const unsigned long int CardSize = 256;
const unsigned long int NotFoundOnAfterSymbol = 20;
const unsigned long int EnsureMarkerObject = 18;
const unsigned long int NotFoundOnSymbol = 19;
const unsigned long int MapFlagRestrictDelegation = 2;
const unsigned long int ObjectSizeMask = 63;
const unsigned long int TagMask = 1;
const unsigned long int FormatPayload = 3;
const unsigned long int InterpreterObject = 17;
const unsigned long int ASCIIStringProto = 7;
const unsigned long int MethodDefinitionProto = 9;
const unsigned long int BCNewClosure = 9;
const unsigned long int BCSendMessage = 0;
const unsigned long int BCStoreVariable = 2;
const unsigned long int IdHashReserved = 8388592;
const unsigned long int LobbyObject = 0;
const unsigned long int BCSendMessageWithOptionals = 11;
const unsigned long int IdHashFree = 8388607;
const unsigned long int BCLoadSelector = 6;
const unsigned long int BCExtended = 15;
const unsigned long int MethodCacheSize = 1024;
const unsigned long int SmallIntTag = 1;
const unsigned long int ObjectTag = 0;
const unsigned long int BreakTableCapacity = 512;
const unsigned long int ApplyToSymbol = 31;
const unsigned long int DivideByZeroSymbol = 29;
const unsigned long int OptionalsSymbol = 32;
const unsigned long int FormatByteArray = 2;
const unsigned long int IdHashBits = 23;
const unsigned long int CompiledMethodWindow = 13;
const unsigned long int FalseObject = 4;
const unsigned long int FormatObject = 0;
const unsigned long int NoRoleObject = 1;
const unsigned long int SmallIntegerProto = 10;
const unsigned long int LexicalContextProto = 16;
const unsigned long int BCResendMessage = 14;
const unsigned long int BCLoadVariable = 1;
const unsigned long int ByteArrayProto = 6;

/*** Globals ***/

struct ObjectHeap * CurrentMemory;
struct MethodCacheEntry methodCache[1024];
unsigned long long int currentDispatchID = 0;
ObjectPointer delegationStack[256];
void (* primitives[]) (struct Interpreter *, ObjectPointer *, unsigned long int, struct OopArray *) = 
{
  _primitive0, _primitive1
  , _primitive2, _primitive3, _primitive4, _primitive5, _primitive6, _primitive7, _primitive8, _primitive9, _primitive10, _primitive11, _primitive12, _primitive13, _primitive14, _primitive15, _primitive16, _primitive17
  , _primitive18, _primitive19, _primitive20, _primitive21, _primitive22, _primitive23, _primitive24, _primitive25, _primitive26, _primitive27, _primitive28, _primitive29, _primitive30, _primitive31, _primitive32, _primitive33
  , _primitive34, _primitive35, _primitive36, _primitive37, _primitive38, _primitive39, _primitive40, _primitive41, _primitive42, _primitive43, _primitive44, _primitive45, _primitive46, _primitive47, _primitive48, _primitive49
  , _primitive50, _primitive51, _primitive52, _primitive53, _primitive54, _primitive55, _primitive56, _primitive57, _primitive58, _primitive59, _primitive60, _primitive61, _primitive62, _primitive63, _primitive64, _primitive65
  , _primitive66, _primitive67, _primitive68, _primitive69, _primitive70, _primitive71, _primitive72, _primitive73, _primitive74, _primitive75, _primitive76, _primitive77, _primitive78, _primitive79, _primitive80, _primitive81
  , _primitive82, _primitive83, _primitive84, _primitive85, _primitive86, _primitive87, _primitive88, _primitive89, _primitive90, _primitive91, _primitive92, _primitive93, _primitive94, _primitive95, _primitive96, _primitive97
  , _primitive98, _primitive99, _primitive100, _primitive101, _primitive102, 
};

/*** Methods ***/

static INLINE Bool signedLongInt_fitsSmallInt(signed long int i)
{
  return (signed long int) (i ^ (i << 1)) >= 0;
}

static INLINE Bool ObjectPointer_isSmallInt(ObjectPointer oop)
{
  return (oop & TagMask) == SmallIntTag;
}

static INLINE Bool ObjectPointer_isObject(ObjectPointer oop)
{
  return (oop & TagMask) == ObjectTag;
}

static INLINE struct Object * ObjectPointer_pointer(ObjectPointer oop)
{
  return (struct Object *) (oop & ~TagMask);
}

static INLINE ObjectPointer PSObject_asObject(struct Object * p)
{
  return (ObjectPointer) ((unsigned long int) p | ObjectTag);
}

static INLINE ObjectPointer PSMap_asObject(struct Map * p)
{
  return (ObjectPointer) ((unsigned long int) p | ObjectTag);
}

static INLINE ObjectPointer unsignedLongInt_asObject(unsigned long int i)
{
  return (ObjectPointer) ((i << 1) | SmallIntTag);
}

static INLINE ObjectPointer signedLongInt_asObject(signed long int i)
{
  return (ObjectPointer) ((i << 1) | SmallIntTag);
}

static INLINE signed long int ObjectPointer_asSmallInt(ObjectPointer oop)
{
  ASSERT(ObjectPointer_isSmallInt(oop));
  
  return (signed long int) oop >> 1;
}

static INLINE Bool PSObjectHeap_hasMarked_(struct ObjectHeap * oh, struct Object * obj)
{
  return (obj -> header).isMarked == oh -> markColor;
}

static INLINE void PSObjectHeap_mark_(struct ObjectHeap * oh, struct Object * obj)
{
  (obj -> header).isMarked = oh -> markColor;
}

static INLINE void PSObjectHeap_unmark_(struct ObjectHeap * oh, struct Object * obj)
{
  (obj -> header).isMarked = oh -> markColor ^ MarkColorMask;
}

static INLINE void PSObjectHeap_markStackPush_(struct ObjectHeap * oh, struct Object * obj)
{
  ASSERT(PSObjectHeap_includes_(oh, (unsigned long int) obj));
  PSObjectHeap_mark_(oh, obj);
  if (oh -> markStackPosition >= MarkStackSize)
    oh -> markStackOverflow = True;
  else
  {
    (oh -> markStack)[oh -> markStackPosition] = obj;
    oh -> markStackPosition = oh -> markStackPosition + 1;
  }
}

static INLINE struct Object * PSObjectHeap_markStackPop(struct ObjectHeap * oh)
{
  ASSERT(oh -> markStackPosition > 0);
  oh -> markStackPosition = oh -> markStackPosition - 1;
  
  return (oh -> markStack)[oh -> markStackPosition];
}

static INLINE void PSObjectHeap_rootStackPush_(struct ObjectHeap * oh, ObjectPointer * root)
{
  ASSERT(PSObjectHeap_includes_(oh, (unsigned long int) ObjectPointer_pointer(*root)));
  (oh -> rootStack)[oh -> rootStackPosition] = root;
  oh -> rootStackPosition = oh -> rootStackPosition + 1;
}

static INLINE void PSObjectHeap_rootStackPop_(struct ObjectHeap * oh, unsigned long int n)
{
  ASSERT((n > 0) && (n <= oh -> rootStackPosition));
  oh -> rootStackPosition = oh -> rootStackPosition - n;
}

static INLINE struct Object * PSObjectHeap_makeFreeHoleAt_sized_(struct ObjectHeap * oh, unsigned long int address, unsigned long int size)
{
  unsigned long int words;
  struct Object * obj;
  
  ASSERT(PSObjectHeap_includes_(oh, address));
  words = size / 4;
  ASSERT(words > 0);
  if (words > ObjectSizeMask)
  {
    struct ObjectPayload * payload;
    
    payload = (struct ObjectPayload *) address;
    payload -> payloadFormat = FormatPayload;
    payload -> payloadSize = size - 8;
    obj = (struct Object *) (payload + 1);
    (obj -> header).objectFormat = FormatByteArray;
    (obj -> header).objectSize = 1;
  }
  else
  {
    obj = (struct Object *) address;
    (obj -> header).objectFormat = FormatObject;
    (obj -> header).objectSize = words;
  }
  (obj -> header).idHash = IdHashFree;
  
  return obj;
}

static INLINE unsigned long int PSObjectHeap_allocationLimit(struct ObjectHeap * oh)
{
  return oh -> nextLive - oh -> lastAllocated;
}

static INLINE void PSObjectHeap_makeFreeHole(struct ObjectHeap * oh)
{
  unsigned long int limit;
  
  limit = PSObjectHeap_allocationLimit(oh);
  if (limit > 0)
    PSObjectHeap_mark_(oh, PSObjectHeap_makeFreeHoleAt_sized_(oh, oh -> lastAllocated, limit));
}

static INLINE Bool PSObjectHeap_isPinned_(struct ObjectHeap * oh, unsigned long int oop)
{
  oop = (oop - (unsigned long int) oh -> memory) / CardSize;
  
  return ((oh -> pinnedCards)[oop / 32] >> (oop % 32)) & 1;
}

static INLINE unsigned long int PSObjectHeap_memorySize(struct ObjectHeap * h)
{
  return (unsigned long int) h -> memoryEnd - (unsigned long int) h -> memory;
}

static INLINE void PWord_copyWords_into_(Word * src, unsigned long int n, Word * dst)
{
  if ((src < dst) && ((src + n) > dst))
  {
    dst+=n;
    src+=n;
    
    {
      do
      {
        --dst;
        --src;
        *dst = *src;
        --n;
      }
      while (n > 0);
    }
  }
  else
    while (n > 0)
    {
      *dst = *src;
      ++dst;
      ++src;
      --n;
    }
}

static INLINE void PByte_copyBytes_into_(Byte * src, unsigned long int n, Byte * dst)
{
  if ((src < dst) && ((src + n) > dst))
  {
    dst+=n;
    src+=n;
    
    {
      do
      {
        --dst;
        --src;
        *dst = *src;
        --n;
      }
      while (n > 0);
    }
  }
  else
    while (n > 0)
    {
      *dst = *src;
      ++dst;
      ++src;
      --n;
    }
}

static INLINE void PWord_fillWords_with_(Word * dst, unsigned long int n, Word value)
{
  while (n > 0)
  {
    *dst = value;
    ++dst;
    --n;
  }
}

static INLINE void PByte_fillBytes_with_(Byte * dst, unsigned long int n, Byte value)
{
  while (n > 0)
  {
    *dst = value;
    ++dst;
    --n;
  }
}

static INLINE unsigned long int PSObject_payloadSize(struct Object * obj)
{
  return ((struct ObjectPayload *) obj - 1) -> payloadSize;
}

static INLINE unsigned long int PSObject_memoryUsage(struct Object * obj)
{
  return (obj -> header).objectFormat == FormatObject?(obj -> header).objectSize * 4:((((obj -> header).objectSize * 4) + PSObject_payloadSize(obj)) + 7) & -4;
}

static INLINE unsigned long int PSObject_wordSize(struct Object * obj)
{
  return (obj -> header).objectFormat == FormatObject?(obj -> header).objectSize:(obj -> header).objectSize + ((PSObject_payloadSize(obj) + 3) / 4);
}

static INLINE unsigned long int PSObject_firstSlotOffset(struct Object * obj)
{
  return 8;
}

static INLINE unsigned long int PSObject_slotCount(struct Object * obj)
{
  return (obj -> header).objectSize - 2;
}

static INLINE unsigned long int PSObject_oopCount(struct Object * obj)
{
  return (obj -> header).objectFormat == FormatOopArray?PSObject_wordSize(obj) - 2:PSObject_slotCount(obj);
}

static INLINE unsigned long int PSObject_lastSlotOffset(struct Object * obj)
{
  return ((obj -> header).objectSize * 4) - 4;
}

static INLINE unsigned long int PSObject_lastOopOffset(struct Object * obj)
{
  return (obj -> header).objectFormat == FormatOopArray?PSObject_lastSlotOffset(obj) + PSObject_payloadSize(obj):PSObject_lastSlotOffset(obj);
}

static INLINE unsigned long int PSObject_arrayOffset(struct Object * obj)
{
  return (obj -> header).objectSize * 4;
}

static INLINE ObjectPointer * PSObject_arrayElements(struct Object * obj)
{
  return (ObjectPointer *) ((Byte *) obj + PSObject_arrayOffset(obj));
}

static INLINE unsigned long int PSObject_arraySize(struct Object * obj)
{
  return (obj -> header).objectFormat == FormatObject?0:(PSObject_payloadSize(obj) + 3) / 4;
}

static INLINE unsigned long int PSObject_totalSize(struct Object * obj)
{
  return PSObject_wordSize(obj) * 4;
}

static INLINE unsigned long int PSObject_byteSize(struct Object * obj)
{
  return (obj -> header).objectFormat == FormatObject?PSObject_arrayOffset(obj):PSObject_arrayOffset(obj) + PSObject_payloadSize(obj);
}

static INLINE ObjectPointer * PSObject_slotValues(struct Object * obj)
{
  return (ObjectPointer *) (obj + 1);
}

static INLINE ObjectPointer PSObject_slotValueAt_(struct Object * obj, unsigned long int index)
{
  return (PSObject_slotValues(obj))[index];
}

static INLINE ObjectPointer PSObject_slotValueAt_put_(struct Object * obj, unsigned long int index, unsigned long int oop)
{
  return (PSObject_slotValues(obj))[index] = oop;
}

static INLINE ObjectPointer PSObject_slotValueAtOffset_(struct Object * obj, unsigned long int offset)
{
  return *((ObjectPointer *) ((Byte *) obj + offset));
}

static INLINE ObjectPointer PSObject_slotValueAtOffset_put_(struct Object * obj, unsigned long int offset, ObjectPointer value)
{
  return *((ObjectPointer *) ((Byte *) obj + offset)) = value;
}

static INLINE signed long int PSByteArray_extractInto_sized_(struct ByteArray * fromArray, Byte * targetBuffer, unsigned long int bufferSize)
{
  unsigned long int payloadSize;
  
  payloadSize = PSObject_payloadSize((struct Object *) fromArray);
  if (bufferSize < payloadSize)
    return -1;
  PByte_copyBytes_into_((Byte *) fromArray -> elements, bufferSize, targetBuffer);
  
  return payloadSize;
}

static INLINE struct Object * PSObjectHeap_cloneSpecial_(struct ObjectHeap * oh, unsigned long int index)
{
  return PSObjectHeap_clone_(oh, ObjectPointer_pointer(PSObjectHeap_specialAt_(oh, index)));
}

static INLINE struct Object * PSObjectHeap_newOopArray_sized_(struct ObjectHeap * oh, unsigned long int index, unsigned long int oops)
{
  return PSObjectHeap_cloneOopArray_sized_(oh, ObjectPointer_pointer(PSObjectHeap_specialAt_(oh, index)), oops);
}

static INLINE struct Object * PSObjectHeap_newByteArray_sized_(struct ObjectHeap * oh, unsigned long int index, unsigned long int bytes)
{
  return PSObjectHeap_cloneByteArray_sized_(oh, ObjectPointer_pointer(PSObjectHeap_specialAt_(oh, index)), bytes);
}

static INLINE struct Object * PSObjectHeap_newByteArray_from_sized_(struct ObjectHeap * oh, unsigned long int index, Byte * buffer, unsigned long int bytes)
{
  struct ByteArray * result;
  
  result = (struct ByteArray *) PSObjectHeap_newByteArray_sized_(oh, index, bytes);
  PByte_copyBytes_into_(buffer, bytes, result -> elements);
  
  return (struct Object *) result;
}

static INLINE unsigned long int PSRoleTable_capacity(struct RoleTable * roles)
{
  return PSObject_arraySize((struct Object *) roles) / 4;
}

static INLINE unsigned long int PSSlotTable_capacity(struct SlotTable * slots)
{
  return PSObject_arraySize((struct Object *) slots) / 2;
}

static INLINE struct Map * PSObjectHeap_cloneMap_(struct ObjectHeap * h, struct Map * map)
{
  return (struct Map *) PSObjectHeap_clone_(h, (struct Object *) map);
}

static INLINE struct Map * PSObject_changeMapTo_(struct Object * obj, struct Map * map)
{
  if ((obj -> map) -> representative == PSObject_asObject(obj))
    (obj -> map) -> representative = CurrentMemory -> NilObject;
  
  return obj -> map = map;
}

static INLINE struct Map * PSObject_makeRepresentativeOf_(struct Object * obj, struct Map * map)
{
  PSObject_changeMapTo_(obj, map);
  map -> representative = PSObject_asObject(obj);
  
  return map;
}

static INLINE struct Map * ObjectPointer_checkMap(ObjectPointer arg)
{
  return ObjectPointer_isSmallInt(arg)?(ObjectPointer_pointer(PSObjectHeap_specialAt_(CurrentMemory, SmallIntegerProto))) -> map:(ObjectPointer_pointer(arg)) -> map;
}

static INLINE struct MethodDefinition * ObjectPointer_checkMethodCacheOn_(ObjectPointer name, ObjectPointer * arguments)
{
  struct MethodCacheEntry * entry;
  struct Map * map;
  struct Symbol * sym;
  
  sym = (struct Symbol *) ObjectPointer_pointer(name);
  map = ObjectPointer_checkMap(arguments[0]);
  entry = &methodCache[(name + (map -> header).idHash) & (MethodCacheSize - 1)];
  if (!(entry -> selector == name))
    return Nil;
  switch (ObjectPointer_asSmallInt(sym -> cacheMask))
  {
    case 1:
      if (!(map == (entry -> maps)[0]))
        return Nil;
      break;
    case 2:
      if (!(ObjectPointer_checkMap(arguments[1]) == (entry -> maps)[1]))
        return Nil;
      break;
    case 4:
      if (!(ObjectPointer_checkMap(arguments[2]) == (entry -> maps)[2]))
        return Nil;
      break;
    case 3:
      if (!((ObjectPointer_checkMap(arguments[0]) == (entry -> maps)[0]) && (ObjectPointer_checkMap(arguments[1]) == (entry -> maps)[1])))
        return Nil;
      break;
    case 5:
      if (!((map == (entry -> maps)[0]) && (ObjectPointer_checkMap(arguments[2]) == (entry -> maps)[2])))
        return Nil;
      break;
    case 6:
      if (!((ObjectPointer_checkMap(arguments[1]) == (entry -> maps)[1]) && (ObjectPointer_checkMap(arguments[2]) == (entry -> maps)[2])))
        return Nil;
      break;
    case 7:
      if (!(((map == (entry -> maps)[0]) && (ObjectPointer_checkMap(arguments[1]) == (entry -> maps)[1])) && (ObjectPointer_checkMap(arguments[2]) == (entry -> maps)[2])))
        return Nil;
      break;
  }
  
  return entry -> method;
}

static INLINE void PSInterpreter_stackPush_(struct Interpreter * i, ObjectPointer oop)
{
  if (i -> stackPointer == i -> stackSize)
    PSInterpreter_growStack(i);
  ((i -> stack) -> elements)[i -> stackPointer] = oop;
  i -> stackPointer = i -> stackPointer + 1;
}

static INLINE void PSInterpreter_stackAllocate_(struct Interpreter * i, unsigned long int n)
{
  if ((i -> stackPointer + n) > i -> stackSize)
  {
    PSInterpreter_growStack(i);
    ASSERT((i -> stackPointer + n) <= i -> stackSize);
  }
  i -> stackPointer = i -> stackPointer + n;
}

static INLINE ObjectPointer PSInterpreter_stackPop(struct Interpreter * i)
{
  if (i -> stackPointer == 0)
    error("Attempted to pop empty interpreter stack.");
  i -> stackPointer = i -> stackPointer - 1;
  
  return ((i -> stack) -> elements)[i -> stackPointer];
}

static INLINE signed long int PSInterpreter_decodeShort(struct Interpreter * i)
{
  unsigned long int n;
  
  n = i -> codePointer;
  i -> codePointer = n + 2;
  
  return (signed short int) ((((i -> method) -> code) -> elements)[n] | ((((i -> method) -> code) -> elements)[n + 1] << 8));
}

static INLINE unsigned long int PSInterpreter_decodeImmediate(struct Interpreter * i)
{
  unsigned long int code;
  unsigned long int val;
  unsigned long int n;
  
  n = i -> codePointer;
  code = (((i -> method) -> code) -> elements)[n];
  val = code & 127;
  while (code >= 128)
  {
    ++n;
    code = (((i -> method) -> code) -> elements)[n];
    val = (val << 7) | (code & 127);
  }
  i -> codePointer = n + 1;
  
  return val;
}

static INLINE void PSInterpreter_sendMessage_withOptionals_(struct Interpreter * i, unsigned long int n, struct OopArray * opts)
{
  ObjectPointer selector;
  ObjectPointer * args;
  
  i -> stackPointer = i -> stackPointer - n;
  args = &((i -> stack) -> elements)[i -> stackPointer];
  selector = PSInterpreter_stackPop(i);
  PSInterpreter_send_to_through_arity_withOptionals_(i, selector, args, args, n, opts);
}

static INLINE void PSInterpreter_sendMessageWithOptionals_(struct Interpreter * i, unsigned long int n)
{
  struct OopArray * opts;
  
  opts = (struct OopArray *) PSInterpreter_stackPop(i);
  PSInterpreter_sendMessage_withOptionals_(i, n, opts);
}

static INLINE void PSInterpreter_send_to_arity_withOptionals_(struct Interpreter * i, ObjectPointer selector, ObjectPointer * args, unsigned long int n, struct OopArray * opts)
{
  PSInterpreter_send_to_through_arity_withOptionals_(i, selector, args, args, n, opts);
}

static INLINE Bool PSInterpreter_dispatchOptionalKeyword_valued_(struct Interpreter * i, ObjectPointer key, ObjectPointer value)
{
  struct OopArray * optKeys;
  
  optKeys = (i -> method) -> optionalKeywords;
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (PSObject_arraySize((struct Object *) optKeys) - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int optKey = _i_;
      
      
      {
        if ((optKeys -> elements)[optKey] == key)
        {
          if ((i -> method) -> heapAllocate == CurrentMemory -> TrueObject)
            ((i -> lexicalContext) -> variables)[ObjectPointer_asSmallInt((i -> method) -> inputVariables) + optKey] = value;
          else
            ((i -> stack) -> elements)[(i -> framePointer + ObjectPointer_asSmallInt((i -> method) -> inputVariables)) + optKey] = value;
          
          return True;
        }
      }
    }
  }
  
  return False;
}

static INLINE void PSInterpreter_loadVariable_(struct Interpreter * i, unsigned long int n)
{
  PSInterpreter_stackPush_(i, (i -> method) -> heapAllocate == CurrentMemory -> TrueObject?((i -> lexicalContext) -> variables)[n]:((i -> stack) -> elements)[i -> framePointer + n]);
}

static INLINE void PSInterpreter_storeVariable_(struct Interpreter * i, unsigned long int n)
{
  if ((i -> method) -> heapAllocate == CurrentMemory -> TrueObject)
    ((i -> lexicalContext) -> variables)[n] = ((i -> stack) -> elements)[i -> stackPointer - 1];
  else
    ((i -> stack) -> elements)[i -> framePointer + n] = ((i -> stack) -> elements)[i -> stackPointer - 1];
}

static INLINE void PSInterpreter_loadFreeVariable_(struct Interpreter * i, unsigned long int n)
{
  PSInterpreter_stackPush_(i, ((((i -> closure) -> lexicalWindow)[n - 1]) -> variables)[PSInterpreter_decodeImmediate(i)]);
}

static INLINE void PSInterpreter_storeFreeVariable_(struct Interpreter * i, unsigned long int n)
{
  ((((i -> closure) -> lexicalWindow)[n - 1]) -> variables)[PSInterpreter_decodeImmediate(i)] = ((i -> stack) -> elements)[i -> stackPointer - 1];
}

static INLINE void PSInterpreter_loadLiteral_(struct Interpreter * i, unsigned long int n)
{
  PSInterpreter_stackPush_(i, (((i -> method) -> literals) -> elements)[n]);
}

static INLINE void PSInterpreter_loadSelector_(struct Interpreter * i, unsigned long int n)
{
  PSInterpreter_stackPush_(i, (((i -> method) -> selectors) -> elements)[n]);
}

static INLINE void PSInterpreter_popStack_(struct Interpreter * i, unsigned long int n)
{
  i -> stackPointer = i -> stackPointer - n;
}

static INLINE void PSInterpreter_newArray_(struct Interpreter * i, unsigned long int n)
{
  struct OopArray * arr;
  unsigned long int stackPointer;
  
  if (n == 0)
  {
    PSInterpreter_stackPush_(i, PSObjectHeap_specialAt_(CurrentMemory, ArrayProto));
    
    return;
  }
  arr = (struct OopArray *) PSObjectHeap_newOopArray_sized_(CurrentMemory, ArrayProto, n);
  stackPointer = i -> stackPointer - n;
  i -> stackPointer = stackPointer;
  PWord_copyWords_into_((Word *) (&((i -> stack) -> elements)[stackPointer]), n, (Word *) PSObject_arrayElements((struct Object *) arr));
  PSInterpreter_stackPush_(i, PSObject_asObject((struct Object *) arr));
}

static INLINE void PSInterpreter_newClosure_(struct Interpreter * i, unsigned long int n)
{
  struct Closure * newClosure;
  
  if ((struct CompiledMethod *) i -> closure == i -> method)
    newClosure = (struct Closure *) PSObjectHeap_newOopArray_sized_(CurrentMemory, ClosureProto, (unsigned long int) 1);
  else
  {
    unsigned long int inheritedSize;
    
    inheritedSize = PSObject_arraySize((struct Object *) i -> closure);
    newClosure = (struct Closure *) PSObjectHeap_newOopArray_sized_(CurrentMemory, ClosureProto, (unsigned long int) (inheritedSize + 1));
    PWord_copyWords_into_((Word *) (i -> closure) -> lexicalWindow, inheritedSize, (Word *) newClosure -> lexicalWindow + 1);
  }
  (newClosure -> lexicalWindow)[0] = i -> lexicalContext;
  newClosure -> method = (struct CompiledMethod *) (((i -> method) -> literals) -> elements)[n];
  PSInterpreter_stackPush_(i, PSObject_asObject((struct Object *) newClosure));
}

static INLINE void PSInterpreter_pushInteger_(struct Interpreter * i, unsigned long int n)
{
  PSInterpreter_stackPush_(i, unsignedLongInt_asObject(n));
}

static INLINE void PSInterpreter_jumpTo(struct Interpreter * i)
{
  signed long int offset;
  
  offset = PSInterpreter_decodeShort(i);
  i -> codePointer = i -> codePointer + offset;
}

static INLINE void PSInterpreter_branchIfTrue(struct Interpreter * i)
{
  signed long int offset;
  ObjectPointer condition;
  
  offset = PSInterpreter_decodeShort(i);
  condition = PSInterpreter_stackPop(i);
  if (condition == CurrentMemory -> TrueObject)
    i -> codePointer = i -> codePointer + offset;
  else
    if (!(condition == CurrentMemory -> FalseObject))
    {
      i -> codePointer = i -> codePointer - 3;
      PSInterpreter_signal_with_(i, NotABooleanSymbol, condition);
    }
}

static INLINE void PSInterpreter_branchIfFalse(struct Interpreter * i)
{
  signed long int offset;
  ObjectPointer condition;
  
  offset = PSInterpreter_decodeShort(i);
  condition = PSInterpreter_stackPop(i);
  if (condition == CurrentMemory -> FalseObject)
    i -> codePointer = i -> codePointer + offset;
  else
    if (!(condition == CurrentMemory -> TrueObject))
    {
      i -> codePointer = i -> codePointer - 3;
      PSInterpreter_signal_with_(i, NotABooleanSymbol, condition);
    }
}

static INLINE void PSInterpreter_pushEnvironment(struct Interpreter * i)
{
  PSInterpreter_stackPush_(i, (i -> method) -> environment);
}

static INLINE void PSInterpreter_pushNil(struct Interpreter * i)
{
  PSInterpreter_stackPush_(i, CurrentMemory -> NilObject);
}

static INLINE void PSInterpreter_pushTrue(struct Interpreter * i)
{
  PSInterpreter_stackPush_(i, CurrentMemory -> TrueObject);
}

static INLINE void PSInterpreter_pushFalse(struct Interpreter * i)
{
  PSInterpreter_stackPush_(i, CurrentMemory -> FalseObject);
}

static INLINE void PSInterpreter_isIdenticalTo(struct Interpreter * i)
{
  if (PSInterpreter_stackPop(i) == PSInterpreter_stackPop(i))
    PSInterpreter_stackPush_(i, CurrentMemory -> TrueObject);
  else
    PSInterpreter_stackPush_(i, CurrentMemory -> FalseObject);
}

void PSObjectHeap_initializeCollector(struct ObjectHeap * oh)
{
  ASSERT(oh -> memoryEnd > 0);
  ASSERT(PSObjectHeap_memoryStart(oh) < oh -> memoryEnd);
  oh -> rootStackPosition = 0;
  oh -> markStackPosition = 0;
  oh -> markStackOverflow = False;
  oh -> markColor = MarkColorMask;
  oh -> lastAllocated = oh -> memoryEnd;
  oh -> nextLive = oh -> memoryEnd;
}

void PSObjectHeap_initializeWithFirstFreeAt_(struct ObjectHeap * oh, unsigned long int firstFree)
{
  if (oh -> nextLive == firstFree)
    oh -> nextLive = oh -> memoryEnd;
  else
    PSObjectHeap_unmark_(oh, PSObjectHeap_makeFreeHoleAt_sized_(oh, firstFree, oh -> memoryEnd - firstFree));
}

void PSObjectHeap_markAndPushSlotsOf_(struct ObjectHeap * oh, struct Object * obj)
{
  struct Object * slotObj;
  ObjectPointer slotOop;
  
  ASSERT(PSObjectHeap_includes_(oh, (unsigned long int) obj));
  oh -> totalAllocated = oh -> totalAllocated + PSObject_memoryUsage(obj);
  if (!(PSObjectHeap_hasMarked_(oh, (struct Object *) obj -> map)))
    PSObjectHeap_markStackPush_(oh, (struct Object *) obj -> map);
  
  {
    unsigned long int _i_ = PSObject_firstSlotOffset(obj);
    unsigned long int _j_ = PSObject_lastOopOffset(obj) + 4;
    
    for (; _i_ < _j_; _i_+=4)
    {
      unsigned long int offset = _i_;
      
      
      {
        slotOop = PSObject_slotValueAtOffset_(obj, offset);
        if (ObjectPointer_isObject(slotOop))
        {
          slotObj = ObjectPointer_pointer(slotOop);
          while ((slotObj -> header).idHash == IdHashForwarded)
          {
            slotObj = ((struct ForwardedObject *) slotObj) -> target;
            PSObject_slotValueAtOffset_put_(obj, offset, PSObject_asObject(slotObj));
          }
          if (!(PSObjectHeap_hasMarked_(oh, slotObj)))
            PSObjectHeap_markStackPush_(oh, slotObj);
        }
      }
    }
  }
}

void PSObjectHeap_markAndTrace(struct ObjectHeap * oh)
{
  oh -> markStackPosition = 0;
  oh -> markStackOverflow = False;
  PSObjectHeap_markAndPushRoots(oh);
  oh -> totalAllocated = 0;
  while (oh -> markStackPosition > 0)
    PSObjectHeap_markAndPushSlotsOf_(oh, PSObjectHeap_markStackPop(oh));
  while (oh -> markStackOverflow)
  {
    PSObjectHeap_recoverMarkStack(oh);
    while (oh -> markStackPosition > 0)
      PSObjectHeap_markAndPushSlotsOf_(oh, PSObjectHeap_markStackPop(oh));
  }
}

void PSObjectHeap_markAndPushRoots(struct ObjectHeap * oh)
{
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (oh -> rootStackPosition - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        struct Object * obj;
        
        obj = ObjectPointer_pointer(*(oh -> rootStack)[index]);
        while ((obj -> header).idHash == IdHashForwarded)
        {
          obj = ((struct ForwardedObject *) obj) -> target;
          *(oh -> rootStack)[index] = PSObject_asObject(obj);
        }
        PSObjectHeap_markStackPush_(oh, obj);
      }
    }
  }
}

Bool PSObjectHeap_needsToMark_(struct ObjectHeap * oh, struct Object * obj)
{
  struct Object * slotObj;
  ObjectPointer slotOop;
  
  ASSERT(PSObjectHeap_includes_(oh, (unsigned long int) obj));
  if (!(PSObjectHeap_hasMarked_(oh, (struct Object *) obj -> map)))
    return True;
  
  {
    unsigned long int _i_ = PSObject_firstSlotOffset(obj);
    unsigned long int _j_ = PSObject_lastOopOffset(obj) + 4;
    
    for (; _i_ < _j_; _i_+=4)
    {
      unsigned long int offset = _i_;
      
      
      {
        slotOop = PSObject_slotValueAtOffset_(obj, offset);
        if (ObjectPointer_isObject(slotOop))
        {
          slotObj = ObjectPointer_pointer(slotOop);
          if (!(PSObjectHeap_hasMarked_(oh, slotObj)))
            return True;
        }
      }
    }
  }
  
  return False;
}

Bool PSObjectHeap_recoverMarkStack(struct ObjectHeap * oh)
{
  unsigned long int offset;
  struct Object * obj;
  
  oh -> markStackOverflow = False;
  oh -> markStackPosition = 0;
  offset = PSObjectHeap_memoryStart(oh);
  while (offset < oh -> memoryEnd)
  {
    obj = (struct Object *) offset;
    if ((obj -> header).objectFormat == FormatPayload)
    {
      offset+=4;
      obj = (struct Object *) offset;
    }
    if (PSObjectHeap_hasMarked_(oh, obj) && PSObjectHeap_needsToMark_(oh, obj))
      PSObjectHeap_markStackPush_(oh, obj);
    if (oh -> markStackOverflow)
      return False;
    offset+=PSObject_totalSize(obj);
  }
  
  return True;
}

void PSObjectHeap_findNextFree(struct ObjectHeap * oh)
{
  unsigned long int color;
  struct Object * obj;
  unsigned long int offset;
  
  offset = oh -> nextLive;
  color = oh -> markColor ^ MarkColorMask;
  while (offset < oh -> memoryEnd)
  {
    obj = (struct Object *) offset;
    if ((obj -> header).objectFormat == FormatPayload)
      obj = (struct Object *) (offset + 4);
    if ((obj -> header).isMarked == color)
    {
      if (((obj -> header).idHash != IdHashFree) && PSObjectHeap_isPinned_(oh, (unsigned long int) obj))
        PSObjectHeap_mark_(oh, obj);
      else
      {
        oh -> lastAllocated = offset;
        
        return;
      }
    }
    offset = (unsigned long int) ((Byte *) obj + PSObject_totalSize(obj));
  }
  oh -> lastAllocated = offset;
}

void PSObjectHeap_findNextLive(struct ObjectHeap * oh)
{
  unsigned long int color;
  struct Object * obj;
  unsigned long int offset;
  
  offset = oh -> lastAllocated;
  color = oh -> markColor;
  while (offset < oh -> memoryEnd)
  {
    obj = (struct Object *) offset;
    if ((obj -> header).objectFormat == FormatPayload)
      obj = (struct Object *) (offset + 4);
    if ((obj -> header).isMarked == color)
    {
      oh -> nextLive = offset;
      
      return;
    }
    else
      if (((obj -> header).idHash != IdHashFree) && PSObjectHeap_isPinned_(oh, (unsigned long int) obj))
      {
        PSObjectHeap_mark_(oh, obj);
        
        {
          oh -> nextLive = offset;
          
          return;
        }
      }
    offset = (unsigned long int) ((Byte *) obj + PSObject_totalSize(obj));
  }
  oh -> nextLive = offset;
}

void PSObjectHeap_sweep(struct ObjectHeap * oh)
{
  PSObjectHeap_makeFreeHole(oh);
  if (oh -> nextLive >= oh -> memoryEnd)
  {
    oh -> lastAllocated = oh -> nextLive;
    
    return;
  }
  PSObjectHeap_findNextFree(oh);
  PSObjectHeap_findNextLive(oh);
}

void PSObjectHeap_garbageCollect(struct ObjectHeap * oh)
{
  while (oh -> lastAllocated < oh -> memoryEnd)
    PSObjectHeap_sweep(oh);
  oh -> markColor = oh -> markColor ^ MarkColorMask;
  PSObjectHeap_markAndTrace(oh);
  PSObjectHeap_clearCards(oh);
  oh -> lastAllocated = PSObjectHeap_memoryStart(oh);
  oh -> nextLive = PSObjectHeap_memoryStart(oh);
}

void PSObjectHeap_clearCards(struct ObjectHeap * oh)
{
  PWord_fillWords_with_((Word *) oh -> pinnedCards, (unsigned long int) ((PSObjectHeap_memorySize(oh) + ((CardSize * 32) - 1)) / (CardSize * 32)), (Word) 0);
}

void PSObjectHeap_pinCards(struct ObjectHeap * oh)
{
  unsigned long int * stack;
  unsigned long int stackTop;
  unsigned long int memorySize;
  
  memorySize = PSObjectHeap_memorySize(oh);
  stack = oh -> stackBottom;
  while (stack > &stackTop)
  {
    unsigned long int offset;
    
    offset = *stack - (unsigned long int) oh -> memory;
    if (offset < memorySize)
    {
      offset/=CardSize;
      (oh -> pinnedCards)[offset / 32] = (oh -> pinnedCards)[offset / 32] | (1 << (offset % 32));
    }
    --stack;
  }
}

ObjectPointer PSObjectHeap_remapOop_(struct ObjectHeap * oh, ObjectPointer oop)
{
  unsigned long int low;
  unsigned long int pivot;
  unsigned long int high;
  
  ASSERT(PSObjectHeap_includes_(oh, (unsigned long int) ObjectPointer_pointer(oop)));
  low = 0;
  high = oh -> breakTableSize - 1;
  pivot = (low + high) / 2;
  while ((high - low) > 1)
  {
    if (oop < ((oh -> breakTable)[pivot]).oldAddress)
      high = pivot - 1;
    else
      low = pivot;
    pivot = (low + high) / 2;
  }
  if (((pivot + 1) < oh -> breakTableSize) && (oop >= ((oh -> breakTable)[pivot + 1]).oldAddress))
    ++pivot;
  if (pivot > (oh -> breakTableSize - 1))
    pivot = oh -> breakTableSize - 1;
  
  return (oop - ((oh -> breakTable)[pivot]).oldAddress) + ((oh -> breakTable)[pivot]).newAddress;
}

void PSObjectHeap_remapOops(struct ObjectHeap * oh)
{
  ObjectPointer oop;
  struct Object * obj;
  
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (oh -> rootStackPosition - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        *(oh -> rootStack)[index] = PSObjectHeap_remapOop_(oh, *(oh -> rootStack)[index]);
      }
    }
  }
  oop = (ObjectPointer) oh -> memory;
  while (oop < oh -> memoryEnd)
  {
    obj = (struct Object *) oop;
    if ((obj -> header).objectFormat == FormatPayload)
      obj = (struct Object *) (oop + 4);
    if (PSObjectHeap_hasMarked_(oh, obj))
    {
      if ((ObjectPointer) obj -> map < ((oh -> breakTable)[oh -> breakTableSize - 1]).oldAddress)
        obj -> map = (struct Map *) PSObjectHeap_remapOop_(oh, (ObjectPointer) obj -> map);
      
      {
        unsigned long int _i_ = PSObject_firstSlotOffset(obj);
        unsigned long int _j_ = PSObject_lastOopOffset(obj) + 4;
        
        for (; _i_ < _j_; _i_+=4)
        {
          unsigned long int offset = _i_;
          
          
          {
            ObjectPointer slotOop;
            
            slotOop = PSObject_slotValueAtOffset_(obj, offset);
            if (ObjectPointer_isObject(slotOop) && (slotOop < ((oh -> breakTable)[oh -> breakTableSize - 1]).oldAddress))
              PSObject_slotValueAtOffset_put_(obj, offset, PSObjectHeap_remapOop_(oh, slotOop));
          }
        }
      }
    }
    oop = PSObject_asObject(obj) + PSObject_totalSize(obj);
  }
}

void PSObjectHeap_compact_(struct ObjectHeap * oh, Bool mostlyCompact)
{
  ObjectPointer oldAddress;
  Bool hole;
  ObjectPointer newAddress;
  
  ObjectPointer_flushMethodCache(CurrentMemory -> NilObject);
  PSObjectHeap_garbageCollect(oh);
  oldAddress = (ObjectPointer) oh -> memory;
  newAddress = oldAddress;
  oh -> breakTableSize = 0;
  if (mostlyCompact)
    PSObjectHeap_pinCards(oh);
  while (oldAddress < oh -> memoryEnd)
  {
    ((oh -> breakTable)[0]).oldAddress = (ObjectPointer) oh -> memory;
    ((oh -> breakTable)[0]).newAddress = (ObjectPointer) oh -> memory;
    oh -> breakTableSize = 1;
    hole = newAddress < oldAddress;
    while (((oh -> breakTableSize + 1) < BreakTableCapacity) && (oldAddress < oh -> memoryEnd))
    {
      unsigned long int objSize;
      struct Object * obj;
      
      obj = (struct Object *) oldAddress;
      if ((obj -> header).objectFormat == FormatPayload)
        obj = (struct Object *) (oldAddress + 4);
      objSize = PSObject_totalSize(obj);
      if (PSObjectHeap_hasMarked_(oh, obj) || PSObjectHeap_isPinned_(oh, (unsigned long int) obj))
      {
        if (oldAddress != newAddress)
        {
          if (PSObjectHeap_isPinned_(oh, (unsigned long int) obj))
          {
            PSObjectHeap_unmark_(oh, PSObjectHeap_makeFreeHoleAt_sized_(oh, (unsigned long int) newAddress, (unsigned long int) (oldAddress - newAddress)));
            newAddress = oldAddress;
            hole = True;
          }
          else
            PWord_copyWords_into_((Word *) oldAddress, (unsigned long int) (((objSize + (ObjectPointer) obj) - oldAddress) / 4), (Word *) newAddress);
          if (hole)
          {
            ((oh -> breakTable)[oh -> breakTableSize]).oldAddress = oldAddress;
            ((oh -> breakTable)[oh -> breakTableSize]).newAddress = newAddress;
            oh -> breakTableSize = oh -> breakTableSize + 1;
            hole = False;
          }
        }
        newAddress = ((newAddress - oldAddress) + (ObjectPointer) obj) + objSize;
      }
      else
        hole = True;
      oldAddress = PSObject_asObject(obj) + objSize;
    }
    if (newAddress < oldAddress)
    {
      PSObjectHeap_unmark_(oh, PSObjectHeap_makeFreeHoleAt_sized_(oh, (unsigned long int) newAddress, (unsigned long int) (oldAddress - newAddress)));
      ((oh -> breakTable)[oh -> breakTableSize]).oldAddress = oldAddress;
      ((oh -> breakTable)[oh -> breakTableSize]).newAddress = oldAddress;
      oh -> breakTableSize = oh -> breakTableSize + 1;
    }
    PSObjectHeap_remapOops(oh);
  }
}

struct ForwardedObject * PSObjectHeap_forward_to_(struct ObjectHeap * oh, struct Object * old, struct Object * new)
{
  struct ForwardedObject * forward;
  unsigned long int oldSize;
  
  ASSERT(PSObjectHeap_includes_(oh, (unsigned long int) old));
  ASSERT(PSObjectHeap_includes_(oh, (unsigned long int) new));
  (new -> header).idHash = (old -> header).idHash;
  forward = (struct ForwardedObject *) old;
  oldSize = PSObject_totalSize(old);
  if (oldSize > 8)
  {
    PSObjectHeap_mark_(oh, PSObjectHeap_makeFreeHoleAt_sized_(oh, (unsigned long int) (forward + 1), (unsigned long int) (oldSize - 8)));
    if (!((old -> header).objectFormat == FormatObject))
      PSObjectHeap_mark_(oh, PSObjectHeap_makeFreeHoleAt_sized_(oh, (unsigned long int) ((struct ObjectPayload *) old - 1), (unsigned long int) 4));
  }
  (forward -> header).objectFormat = FormatObject;
  (forward -> header).idHash = IdHashForwarded;
  (forward -> header).objectSize = 2;
  forward -> target = new;
  
  return forward;
}

void PSObjectHeap_findHoleSized_(struct ObjectHeap * oh, unsigned long int size)
{
  ASSERT(size > 0);
  PSObjectHeap_pinCards(oh);
  while (oh -> nextLive < oh -> memoryEnd)
  {
    PSObjectHeap_sweep(oh);
    if (PSObjectHeap_allocationLimit(oh) >= size)
    {
      return;
    }
  }
  PSObjectHeap_garbageCollect(oh);
  PSObjectHeap_pinCards(oh);
  if ((oh -> totalAllocated > ((PSObjectHeap_memorySize(oh) * 3) / 4)) && (oh -> memoryEnd < oh -> memoryLimit))
    PSObjectHeap_growBy_(oh, oh -> growthHeadroom < (oh -> memoryLimit - oh -> memoryEnd)?oh -> growthHeadroom:oh -> memoryLimit - oh -> memoryEnd);
  while (oh -> nextLive < oh -> memoryEnd)
  {
    PSObjectHeap_sweep(oh);
    if (PSObjectHeap_allocationLimit(oh) >= size)
    {
      return;
    }
  }
  PSObjectHeap_compact_(oh, True);
  while (oh -> nextLive < oh -> memoryEnd)
  {
    PSObjectHeap_sweep(oh);
    if (PSObjectHeap_allocationLimit(oh) >= size)
    {
      return;
    }
  }
  PSObjectHeap_growBy_(oh, (oh -> growthHeadroom < (oh -> memoryLimit - oh -> memoryEnd)?oh -> growthHeadroom:oh -> memoryLimit - oh -> memoryEnd) < (size - PSObjectHeap_allocationLimit(oh))?size - PSObjectHeap_allocationLimit(oh):(oh -> growthHeadroom < (oh -> memoryLimit - oh -> memoryEnd)?oh -> growthHeadroom:oh -> memoryLimit - oh -> memoryEnd));
}

struct Object * PSObjectHeap_allocateChunkSized_withPayload_(struct ObjectHeap * oh, unsigned long int words, unsigned long int payloadSize)
{
  unsigned long int size;
  struct Object * obj;
  struct ObjectPayload * payload;
  
  size = ((words * 4) + 4) + ((payloadSize + 3) & -4);
  ASSERT((words > 0) && (payloadSize >= 0));
  if (PSObjectHeap_allocationLimit(oh) < size)
    PSObjectHeap_findHoleSized_(oh, size);
  payload = (struct ObjectPayload *) oh -> lastAllocated;
  oh -> lastAllocated = oh -> lastAllocated + size;
  payload -> payloadFormat = FormatPayload;
  payload -> payloadSize = payloadSize;
  obj = (struct Object *) (payload + 1);
  PSObjectHeap_mark_(oh, obj);
  (obj -> header).objectSize = words;
  
  return obj;
}

struct Object * PSObjectHeap_allocateChunkSized_(struct ObjectHeap * oh, unsigned long int words)
{
  unsigned long int size;
  struct Object * obj;
  
  ASSERT(words > 0);
  size = words * 4;
  if (PSObjectHeap_allocationLimit(oh) < size)
    PSObjectHeap_findHoleSized_(oh, size);
  obj = (struct Object *) oh -> lastAllocated;
  ASSERT(PSObjectHeap_includes_(oh, (unsigned long int) obj));
  oh -> lastAllocated = oh -> lastAllocated + size;
  PSObjectHeap_mark_(oh, obj);
  (obj -> header).objectSize = words;
  
  return obj;
}

Bool PSObjectHeap_isFree_(struct ObjectHeap * oh, ObjectPointer oop)
{
  struct Object * obj;
  
  obj = ObjectPointer_pointer(oop);
  
  return !PSObjectHeap_hasMarked_(oh, obj) || ((obj -> header).idHash >= IdHashReserved);
}

ObjectPointer PSObjectHeap_firstObject(struct ObjectHeap * h)
{
  ObjectPointer oop;
  
  oop = PSObjectHeap_memoryStart(h);
  if (((ObjectPointer_pointer(oop)) -> header).objectFormat == FormatPayload)
    oop+=4;
  
  return oop;
}

ObjectPointer PSObjectHeap_objectAfter_(struct ObjectHeap * oh, ObjectPointer oop)
{
  ASSERT(PSObjectHeap_includes_(oh, (unsigned long int) oop) && (PSObject_totalSize(ObjectPointer_pointer(oop)) > 0));
  if (oop >= oh -> memoryEnd)
    error("No objects after the end of memory");
  oop+=PSObject_totalSize(ObjectPointer_pointer(oop));
  if ((oop >= oh -> lastAllocated) && (oop < oh -> nextLive))
    oop = oh -> nextLive;
  if (((ObjectPointer_pointer(oop)) -> header).objectFormat == FormatPayload)
    oop+=4;
  
  return oop;
}

ObjectPointer PSObjectHeap_specialAt_(struct ObjectHeap * h, unsigned long int index)
{
  return (PSObject_arrayElements(ObjectPointer_pointer(h -> specialObjectsOop)))[index];
}

void PSObjectHeap_adjustFieldsOf_by_(struct ObjectHeap * h, ObjectPointer oop, signed long int shiftAmountInBytes)
{
  struct Object * ptr;
  ObjectPointer fieldOop;
  
  ptr = ObjectPointer_pointer(oop);
  ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ptr));
  ptr -> map = (struct Map *) ((Byte *) ptr -> map + shiftAmountInBytes);
  
  {
    unsigned long int _i_ = PSObject_firstSlotOffset(ptr);
    unsigned long int _j_ = PSObject_lastOopOffset(ptr) + 4;
    
    for (; _i_ < _j_; _i_+=4)
    {
      unsigned long int offset = _i_;
      
      
      {
        fieldOop = PSObject_slotValueAtOffset_(ptr, offset);
        if (ObjectPointer_isObject(fieldOop))
          PSObject_slotValueAtOffset_put_(ptr, offset, (ObjectPointer) (fieldOop + shiftAmountInBytes));
      }
    }
  }
}

unsigned long int PSObjectHeap_adjustAllOopsBy_(struct ObjectHeap * h, unsigned long int shiftAmountInBytes)
{
  ObjectPointer oop;
  unsigned long int total;
  
  if (shiftAmountInBytes == 0)
    return 0;
  total = 0;
  oop = PSObjectHeap_firstObject(h);
  while (oop < h -> memoryEnd)
  {
    if (!(PSObjectHeap_isFree_(h, oop)))
    {
      ++total;
      PSObjectHeap_adjustFieldsOf_by_(h, oop, (signed long int) shiftAmountInBytes);
    }
    oop = PSObjectHeap_objectAfter_(h, oop);
  }
  
  return total;
}

void PSObjectHeap_initializeWithShift_(struct ObjectHeap * h, unsigned long int shiftAmountInBytes)
{
  PSObjectHeap_initializeCollector(h);
  h -> totalObjectCount = PSObjectHeap_adjustAllOopsBy_(h, shiftAmountInBytes);
  h -> specialObjectsOop = h -> specialObjectsOop + shiftAmountInBytes;
  PSObjectHeap_rootStackPush_(h, &h -> specialObjectsOop);
  h -> NilObject = PSObjectHeap_specialAt_(h, NilObject);
  PSObjectHeap_rootStackPush_(h, &h -> NilObject);
  h -> TrueObject = PSObjectHeap_specialAt_(h, TrueObject);
  PSObjectHeap_rootStackPush_(h, &h -> TrueObject);
  h -> FalseObject = PSObjectHeap_specialAt_(h, FalseObject);
  PSObjectHeap_rootStackPush_(h, &h -> FalseObject);
  h -> ClosureWindow = PSObjectHeap_specialAt_(h, ClosureWindow);
  PSObjectHeap_rootStackPush_(h, &h -> ClosureWindow);
  h -> CompiledMethodWindow = PSObjectHeap_specialAt_(h, CompiledMethodWindow);
  PSObjectHeap_rootStackPush_(h, &h -> CompiledMethodWindow);
  h -> PrimitiveMethodWindow = PSObjectHeap_specialAt_(h, PrimitiveMethodWindow);
  PSObjectHeap_rootStackPush_(h, &h -> PrimitiveMethodWindow);
  h -> growthHeadroom = 4 << 20;
  h -> shrinkThreshold = 8 << 20;
}

unsigned long int PSObjectHeap_memoryStart(struct ObjectHeap * h)
{
  return (unsigned long int) h -> memory;
}

Bool PSObjectHeap_includes_(struct ObjectHeap * h, unsigned long int address)
{
  return (address >= PSObjectHeap_memoryStart(h)) && (address < h -> memoryEnd);
}

void PSObjectHeap_checkValid_(struct ObjectHeap * h, unsigned long int address)
{
  if (address < PSObjectHeap_memoryStart(h))
    error("Bad address: too low.");
  if (address >= h -> memoryEnd)
    error("Bad address: past the end of the heap.");
}

ObjectPointer PSObjectHeap_firstAccessibleObject(struct ObjectHeap * h)
{
  ObjectPointer obj;
  
  obj = PSObjectHeap_firstObject(h);
  while (obj < h -> memoryEnd)
  {
    if (!(PSObjectHeap_isFree_(h, obj)))
      return obj;
    obj = PSObjectHeap_objectAfter_(h, obj);
  }
  error("The heap is empty");
  
  return 0;
}

ObjectPointer PSObjectHeap_accessibleObjectAfter_(struct ObjectHeap * h, ObjectPointer oop)
{
  ObjectPointer obj;
  
  ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(oop)));
  obj = PSObjectHeap_objectAfter_(h, oop);
  ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(obj)));
  while (obj < h -> memoryEnd)
  {
    ASSERT(PSObjectHeap_includes_(h, (unsigned long int) obj));
    if (!(PSObjectHeap_isFree_(h, obj)))
      return obj;
    obj = PSObjectHeap_objectAfter_(h, obj);
  }
  
  return 0;
}

ObjectPointer PSObjectHeap_initialInstanceOfMap_(struct ObjectHeap * h, struct Map * map)
{
  ObjectPointer thisObj;
  
  ASSERT(PSObjectHeap_includes_(h, (unsigned long int) map));
  thisObj = PSObjectHeap_firstAccessibleObject(h);
  while (!(thisObj == 0))
  {
    ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(thisObj)));
    if ((ObjectPointer_pointer(thisObj)) -> map == map)
      return thisObj;
    thisObj = PSObjectHeap_accessibleObjectAfter_(h, thisObj);
  }
  
  return 0;
}

ObjectPointer PSObjectHeap_nextInstanceOfMap_after_(struct ObjectHeap * h, struct Map * map, ObjectPointer oop)
{
  ObjectPointer thisObj;
  
  ASSERT(PSObjectHeap_includes_(h, (unsigned long int) map));
  thisObj = PSObjectHeap_accessibleObjectAfter_(h, oop);
  while (!(thisObj == 0))
  {
    ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(thisObj)));
    if ((ObjectPointer_pointer(thisObj)) -> map == map)
      return thisObj;
    thisObj = PSObjectHeap_accessibleObjectAfter_(h, thisObj);
  }
  
  return 0;
}

ObjectPointer PSObjectHeap_initialDelegateTo_(struct ObjectHeap * h, ObjectPointer parentOop)
{
  ObjectPointer thisObj;
  ObjectPointer thisParent;
  unsigned long int numDelegates;
  
  ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(parentOop)));
  thisObj = PSObjectHeap_firstAccessibleObject(h);
  while (!(thisObj == 0))
  {
    numDelegates = PSObject_arraySize((struct Object *) ((ObjectPointer_pointer(thisObj)) -> map) -> delegates);
    
    {
      unsigned long int _i_ = 0;
      unsigned long int _j_ = (numDelegates - 1) + 1;
      
      for (; _i_ < _j_; _i_+=1)
      {
        unsigned long int index = _i_;
        
        
        {
          thisParent = PSObject_slotValueAt_(ObjectPointer_pointer(thisObj), index);
          if (thisParent == parentOop)
            return thisObj;
        }
      }
    }
    thisObj = PSObjectHeap_accessibleObjectAfter_(h, thisObj);
  }
  
  return 0;
}

ObjectPointer PSObjectHeap_nextDelegateTo_after_(struct ObjectHeap * h, ObjectPointer parentOop, ObjectPointer oop)
{
  ObjectPointer thisObj;
  ObjectPointer thisParent;
  unsigned long int numDelegates;
  
  ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(parentOop)));
  ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(oop)));
  thisObj = PSObjectHeap_accessibleObjectAfter_(h, oop);
  while (!(thisObj == 0))
  {
    numDelegates = PSObject_arraySize((struct Object *) ((ObjectPointer_pointer(thisObj)) -> map) -> delegates);
    
    {
      unsigned long int _i_ = 0;
      unsigned long int _j_ = (numDelegates - 1) + 1;
      
      for (; _i_ < _j_; _i_+=1)
      {
        unsigned long int index = _i_;
        
        
        {
          thisParent = PSObject_slotValueAt_(ObjectPointer_pointer(thisObj), index);
          ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(thisParent)));
          if (thisParent == parentOop)
            return thisObj;
        }
      }
    }
    thisObj = PSObjectHeap_accessibleObjectAfter_(h, thisObj);
  }
  
  return 0;
}

ObjectPointer PSObjectHeap_firstReferringTo_(struct ObjectHeap * h, ObjectPointer targetOop)
{
  ObjectPointer thisSlot;
  ObjectPointer thisObj;
  unsigned long int slotCount;
  
  ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(targetOop)));
  thisObj = PSObjectHeap_firstAccessibleObject(h);
  while (!(thisObj == 0))
  {
    slotCount = ObjectPointer_asSmallInt(((ObjectPointer_pointer(thisObj)) -> map) -> slotCount);
    
    {
      unsigned long int _i_ = 0;
      unsigned long int _j_ = (slotCount - 1) + 1;
      
      for (; _i_ < _j_; _i_+=1)
      {
        unsigned long int index = _i_;
        
        
        {
          thisSlot = PSObject_slotValueAt_(ObjectPointer_pointer(thisObj), index);
          if (thisSlot == targetOop)
            return thisObj;
        }
      }
    }
    thisObj = PSObjectHeap_accessibleObjectAfter_(h, thisObj);
  }
  
  return 0;
}

ObjectPointer PSObjectHeap_nextReferringTo_after_(struct ObjectHeap * h, ObjectPointer targetOop, ObjectPointer oop)
{
  ObjectPointer thisSlot;
  ObjectPointer thisObj;
  unsigned long int slotCount;
  
  ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(targetOop)));
  ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(oop)));
  thisObj = PSObjectHeap_accessibleObjectAfter_(h, oop);
  while (!(thisObj == 0))
  {
    slotCount = ObjectPointer_asSmallInt(((ObjectPointer_pointer(thisObj)) -> map) -> slotCount);
    
    {
      unsigned long int _i_ = 0;
      unsigned long int _j_ = (slotCount - 1) + 1;
      
      for (; _i_ < _j_; _i_+=1)
      {
        unsigned long int index = _i_;
        
        
        {
          thisSlot = PSObject_slotValueAt_(ObjectPointer_pointer(thisObj), index);
          ASSERT(PSObjectHeap_includes_(h, (unsigned long int) ObjectPointer_pointer(thisSlot)));
          if (thisSlot == targetOop)
            return thisObj;
        }
      }
    }
    thisObj = PSObjectHeap_accessibleObjectAfter_(h, thisObj);
  }
  
  return 0;
}

unsigned long int PSObjectHeap_newIdentityHash(struct ObjectHeap * h)
{
  unsigned long int hash;
  
  
  {
    do
    {
      hash = (h -> lastHash = 13849 + (27181 * h -> lastHash)) & 8388607;
    }
    while (hash >= IdHashReserved);
  }
  
  return hash;
}

void PSObjectHeap_growBy_(struct ObjectHeap * h, unsigned long int delta)
{
  unsigned long int oldEnd;
  
  ASSERT(delta > 0);
  oldEnd = h -> memoryEnd;
  growMemoryBy(h, delta);
  if (!(oldEnd == h -> memoryEnd))
    PSObjectHeap_initializeWithFirstFreeAt_(h, oldEnd);
}

void PSObjectHeap_shrinkBy_(struct ObjectHeap * h, unsigned long int delta)
{
  ASSERT(delta > 0);
  shrinkMemoryBy(h, delta);
  if (!(h -> memoryEnd == h -> memoryLimit))
    PSObjectHeap_initializeWithFirstFreeAt_(h, h -> memoryEnd);
}

struct Object * PSObjectHeap_clone_(struct ObjectHeap * oh, struct Object * obj)
{
  struct Object * newObj;
  
  if ((obj -> header).objectFormat == FormatObject)
    newObj = PSObjectHeap_allocateChunkSized_(oh, (obj -> header).objectSize);
  else
    newObj = PSObjectHeap_allocateChunkSized_withPayload_(oh, (obj -> header).objectSize, PSObject_payloadSize(obj));
  (newObj -> header).objectFormat = (obj -> header).objectFormat;
  (newObj -> header).idHash = PSObjectHeap_newIdentityHash(oh);
  PWord_copyWords_into_((Word *) obj + 1, (unsigned long int) (PSObject_wordSize(obj) - 1), (Word *) newObj + 1);
  
  return newObj;
}

struct Object * PSObjectHeap_cloneOopArray_sized_(struct ObjectHeap * oh, struct Object * proto, unsigned long int oops)
{
  struct Object * newObj;
  
  newObj = PSObjectHeap_allocateChunkSized_withPayload_(oh, (proto -> header).objectSize, (unsigned long int) (oops * 4));
  (newObj -> header).objectFormat = FormatOopArray;
  (newObj -> header).idHash = PSObjectHeap_newIdentityHash(oh);
  PWord_copyWords_into_((Word *) proto + 1, (unsigned long int) ((proto -> header).objectSize - 1), (Word *) newObj + 1);
  PWord_fillWords_with_((Word *) newObj + (proto -> header).objectSize, oops, (Word) CurrentMemory -> NilObject);
  
  return newObj;
}

struct Object * PSObjectHeap_cloneByteArray_sized_(struct ObjectHeap * oh, struct Object * proto, unsigned long int bytes)
{
  struct Object * newObj;
  
  newObj = PSObjectHeap_allocateChunkSized_withPayload_(oh, (proto -> header).objectSize, bytes);
  (newObj -> header).objectFormat = FormatByteArray;
  (newObj -> header).idHash = PSObjectHeap_newIdentityHash(oh);
  PWord_copyWords_into_((Word *) proto + 1, (unsigned long int) ((proto -> header).objectSize - 1), (Word *) newObj + 1);
  PWord_fillWords_with_((Word *) newObj + (proto -> header).objectSize, (unsigned long int) ((bytes + 3) / 4), (Word) 0);
  
  return newObj;
}

unsigned long int PSRoleTable_emptySpace(struct RoleTable * roles)
{
  unsigned long int space;
  
  space = 0;
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (PSRoleTable_capacity(roles) - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        if (((roles -> roles)[index]).name == CurrentMemory -> NilObject)
          ++space;
      }
    }
  }
  
  return space;
}

unsigned long int PSRoleTable_minimumCapacityAccommodating_(struct RoleTable * roles, signed long int n)
{
  unsigned long int tableSize;
  unsigned long int requested;
  
  tableSize = PSRoleTable_capacity(roles);
  ASSERT((tableSize + n) >= 0);
  requested = tableSize + n;
  while (tableSize > requested)
    tableSize>>=1;
  if (((tableSize == 0) && requested) > 0)
    tableSize = 1;
  while (tableSize < requested)
    tableSize<<=1;
  
  return tableSize;
}

struct RoleEntry * PSRoleTable_hashEntryForName_(struct RoleTable * roles, ObjectPointer name)
{
  unsigned long int hash;
  unsigned long int tableSize;
  struct RoleEntry * role;
  
  tableSize = PSRoleTable_capacity(roles);
  if (tableSize == 0)
    return Nil;
  hash = ((ObjectPointer_pointer(name)) -> header).idHash & (tableSize - 1);
  
  {
    unsigned long int _i_ = hash;
    unsigned long int _j_ = (tableSize - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        role = &(roles -> roles)[index];
        if (role -> name == name)
          return role;
        if (role -> name == CurrentMemory -> NilObject)
          return Nil;
      }
    }
  }
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (hash - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        role = &(roles -> roles)[index];
        if (role -> name == name)
          return role;
        if (role -> name == CurrentMemory -> NilObject)
          return Nil;
      }
    }
  }
  
  return Nil;
}

struct RoleEntry * PSRoleTable_hashEntryForInsertingName_(struct RoleTable * roles, ObjectPointer name)
{
  unsigned long int hash;
  unsigned long int tableSize;
  struct RoleEntry * role;
  
  tableSize = PSRoleTable_capacity(roles);
  if (tableSize == 0)
    return Nil;
  hash = ((ObjectPointer_pointer(name)) -> header).idHash & (tableSize - 1);
  
  {
    unsigned long int _i_ = hash;
    unsigned long int _j_ = (tableSize - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        role = &(roles -> roles)[index];
        if (role -> name == CurrentMemory -> NilObject)
          return role;
      }
    }
  }
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (hash - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        role = &(roles -> roles)[index];
        if (role -> name == CurrentMemory -> NilObject)
          return role;
      }
    }
  }
  
  return Nil;
}

struct RoleTable * PSRoleTable_growBy_excluding_(struct RoleTable * roles, signed long int n, struct MethodDefinition * method)
{
  unsigned long int newSize;
  unsigned long int oldSize;
  struct RoleTable * newRoles;
  
  oldSize = PSRoleTable_capacity(roles);
  newSize = PSRoleTable_minimumCapacityAccommodating_(roles, ((signed long int) (oldSize / 3) - PSRoleTable_emptySpace(roles)) + n);
  newRoles = (struct RoleTable *) PSObjectHeap_newOopArray_sized_(CurrentMemory, ArrayProto, (unsigned long int) (newSize * 4));
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (oldSize - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        ObjectPointer roleName;
        
        roleName = ((roles -> roles)[index]).name;
        if (!((roleName == CurrentMemory -> NilObject) || (((roles -> roles)[index]).methodDefinition == method)))
        {
          struct RoleEntry * chain;
          struct RoleEntry * role;
          
          role = PSRoleTable_hashEntryForInsertingName_(newRoles, roleName);
          chain = PSRoleTable_hashEntryForName_(newRoles, roleName);
          if (chain != Nil)
          {
            while (!(chain -> nextRole == CurrentMemory -> NilObject))
              chain = &(newRoles -> roles)[ObjectPointer_asSmallInt(chain -> nextRole)];
            chain -> nextRole = unsignedLongInt_asObject((unsigned long int) (role - newRoles -> roles));
          }
          *role = (roles -> roles)[index];
          role -> nextRole = CurrentMemory -> NilObject;
        }
      }
    }
  }
  
  return newRoles;
}

unsigned long int PSSlotTable_emptySpace(struct SlotTable * slots)
{
  unsigned long int space;
  
  space = 0;
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (PSSlotTable_capacity(slots) - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        if (((slots -> slots)[index]).name == CurrentMemory -> NilObject)
          ++space;
      }
    }
  }
  
  return space;
}

struct SlotEntry * PSSlotTable_hashEntryForName_(struct SlotTable * slots, ObjectPointer name)
{
  unsigned long int hash;
  unsigned long int tableSize;
  struct SlotEntry * slot;
  
  tableSize = PSSlotTable_capacity(slots);
  if (tableSize == 0)
    return Nil;
  hash = ((ObjectPointer_pointer(name)) -> header).idHash & (tableSize - 1);
  
  {
    unsigned long int _i_ = hash;
    unsigned long int _j_ = (tableSize - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        slot = &(slots -> slots)[index];
        if (slot -> name == name)
          return slot;
        if (slot -> name == CurrentMemory -> NilObject)
          return Nil;
      }
    }
  }
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (hash - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        slot = &(slots -> slots)[index];
        if (slot -> name == name)
          return slot;
        if (slot -> name == CurrentMemory -> NilObject)
          return Nil;
      }
    }
  }
  
  return Nil;
}

struct SlotEntry * PSSlotTable_hashEntryForInsertingName_(struct SlotTable * slots, ObjectPointer name)
{
  unsigned long int hash;
  unsigned long int tableSize;
  struct SlotEntry * slot;
  
  tableSize = PSSlotTable_capacity(slots);
  if (tableSize == 0)
    return Nil;
  hash = ((ObjectPointer_pointer(name)) -> header).idHash & (tableSize - 1);
  
  {
    unsigned long int _i_ = hash;
    unsigned long int _j_ = (tableSize - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        slot = &(slots -> slots)[index];
        if (slot -> name == CurrentMemory -> NilObject)
          return slot;
      }
    }
  }
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (hash - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        slot = &(slots -> slots)[index];
        if (slot -> name == CurrentMemory -> NilObject)
          return slot;
      }
    }
  }
  
  return Nil;
}

unsigned long int PSSlotTable_minimumCapacityAccommodating_(struct SlotTable * slots, signed long int n)
{
  unsigned long int tableSize;
  unsigned long int requested;
  
  tableSize = PSSlotTable_capacity(slots);
  ASSERT((tableSize + n) >= 0);
  requested = tableSize + n;
  while (tableSize > requested)
    tableSize>>=1;
  if (((tableSize == 0) && requested) > 0)
    tableSize = 1;
  while (tableSize < requested)
    tableSize<<=1;
  
  return tableSize;
}

struct SlotTable * PSSlotTable_growBy_excluding_(struct SlotTable * slots, signed long int n, ObjectPointer name)
{
  unsigned long int newSize;
  struct SlotTable * newSlots;
  unsigned long int oldSize;
  
  oldSize = PSSlotTable_capacity(slots);
  newSize = PSSlotTable_minimumCapacityAccommodating_(slots, ((signed long int) (oldSize / 3) - PSSlotTable_emptySpace(slots)) + n);
  newSlots = (struct SlotTable *) PSObjectHeap_newOopArray_sized_(CurrentMemory, ArrayProto, (unsigned long int) (newSize * 2));
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (oldSize - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        ObjectPointer slotName;
        
        slotName = ((slots -> slots)[index]).name;
        if (!((slotName == CurrentMemory -> NilObject) || (slotName == name)))
        {
          struct SlotEntry * slot;
          
          slot = PSSlotTable_hashEntryForInsertingName_(newSlots, slotName);
          *slot = (slots -> slots)[index];
        }
      }
    }
  }
  
  return newSlots;
}

void PSSlotTable_relocateAll_above_by_(struct SlotTable * slots, unsigned long int type, unsigned long int offset, signed long int amount)
{
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (PSSlotTable_capacity(slots) - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        unsigned long int oldOffset;
        
        if (!(((slots -> slots)[index]).name == CurrentMemory -> NilObject))
        {
          oldOffset = ObjectPointer_asSmallInt(((slots -> slots)[index]).offset);
          if (((oldOffset & SlotTypeMask) == type) && ((oldOffset & SlotOffsetMask) >= offset))
            ((slots -> slots)[index]).offset = signedLongInt_asObject(oldOffset + amount);
        }
      }
    }
  }
}

struct Object * PSObject_addSlotNamed_valued_at_(struct Object * obj, ObjectPointer name, ObjectPointer value, unsigned long int offset)
{
  struct SlotEntry * entry;
  struct Map * map;
  struct Object * newObj;
  
  entry = PSSlotTable_hashEntryForName_((obj -> map) -> slotTable, name);
  if (entry != Nil)
    return Nil;
  map = PSObjectHeap_cloneMap_(CurrentMemory, obj -> map);
  PSObjectHeap_rootStackPush_(CurrentMemory, (ObjectPointer *) (&map));
  map -> slotTable = PSSlotTable_growBy_excluding_(map -> slotTable, 1, CurrentMemory -> NilObject);
  PSSlotTable_relocateAll_above_by_(map -> slotTable, SlotTypeData, offset, 4);
  entry = PSSlotTable_hashEntryForInsertingName_(map -> slotTable, name);
  entry -> name = name;
  entry -> offset = unsignedLongInt_asObject(offset | SlotTypeData);
  if ((obj -> header).objectSize == ObjectSizeMask)
  {
    newObj = PSObjectHeap_allocateChunkSized_withPayload_(CurrentMemory, ObjectSizeMask, (unsigned long int) ((obj -> header).objectFormat == FormatObject?4:PSObject_payloadSize(obj) + 4));
    (newObj -> header).objectFormat = FormatOopArray;
  }
  else
  {
    if ((obj -> header).objectFormat == FormatObject)
      newObj = PSObjectHeap_allocateChunkSized_(CurrentMemory, (unsigned long int) ((obj -> header).objectSize + 1));
    else
      newObj = PSObjectHeap_allocateChunkSized_withPayload_(CurrentMemory, (unsigned long int) ((obj -> header).objectSize + 1), PSObject_payloadSize(obj));
    (newObj -> header).objectFormat = (obj -> header).objectFormat;
  }
  PSObjectHeap_rootStackPop_(CurrentMemory, (unsigned long int) 1);
  (newObj -> header).idHash = PSObjectHeap_newIdentityHash(CurrentMemory);
  PByte_copyBytes_into_((Byte *) obj + PSObject_firstSlotOffset(obj), offset - PSObject_firstSlotOffset(obj), (Byte *) newObj + PSObject_firstSlotOffset(newObj));
  PSObject_slotValueAtOffset_put_(newObj, offset, value);
  PByte_copyBytes_into_((Byte *) obj + offset, PSObject_totalSize(obj) - offset, ((Byte *) newObj + offset) + 4);
  newObj -> map = map;
  map -> representative = PSObject_asObject(newObj);
  
  return newObj;
}

struct Object * PSObject_addSlotNamed_valued_(struct Object * obj, ObjectPointer name, ObjectPointer value)
{
  struct Object * newObj;
  
  newObj = PSObject_addSlotNamed_valued_at_(obj, name, value, (unsigned long int) (PSObject_firstSlotOffset(obj) + (ObjectPointer_asSmallInt((obj -> map) -> slotCount) * 4)));
  if (newObj == Nil)
    return obj;
  (newObj -> map) -> slotCount = signedLongInt_asObject(ObjectPointer_asSmallInt((newObj -> map) -> slotCount) + 1);
  
  return newObj;
}

struct Object * PSObject_addDelegateNamed_valued_at_(struct Object * obj, ObjectPointer name, ObjectPointer value, unsigned long int offset)
{
  unsigned long int delsSize;
  unsigned long int pos;
  struct OopArray * newDels;
  struct OopArray * oldDels;
  struct Map * map;
  struct SlotEntry * entry;
  
  entry = PSSlotTable_hashEntryForName_((obj -> map) -> slotTable, name);
  if (entry != Nil)
    return Nil;
  map = PSObjectHeap_cloneMap_(CurrentMemory, obj -> map);
  PSObjectHeap_rootStackPush_(CurrentMemory, (ObjectPointer *) (&map));
  map -> slotTable = PSSlotTable_growBy_excluding_(map -> slotTable, 1, CurrentMemory -> NilObject);
  PSSlotTable_relocateAll_above_by_(map -> slotTable, SlotTypeDelegate, offset, 4);
  entry = PSSlotTable_hashEntryForInsertingName_(map -> slotTable, name);
  entry -> name = name;
  entry -> offset = unsignedLongInt_asObject(offset | SlotTypeDelegate);
  oldDels = map -> delegates;
  delsSize = PSObject_arraySize((struct Object *) oldDels);
  newDels = (struct OopArray *) PSObjectHeap_newOopArray_sized_(CurrentMemory, ArrayProto, (unsigned long int) (delsSize + 1));
  PSObjectHeap_rootStackPop_(CurrentMemory, (unsigned long int) 1);
  pos = (offset - PSObject_arrayOffset((struct Object *) oldDels)) / 4;
  PWord_copyWords_into_((Word *) oldDels -> elements, pos, (Word *) newDels -> elements);
  PSObject_slotValueAtOffset_put_((struct Object *) newDels, offset, value);
  PWord_copyWords_into_((Word *) oldDels -> elements + pos, delsSize - pos, ((Word *) newDels -> elements + pos) + 1);
  map -> delegates = newDels;
  PSObject_changeMapTo_(obj, map);
  
  return obj;
}

struct Object * PSObject_addDelegateNamed_valued_(struct Object * obj, ObjectPointer name, ObjectPointer value)
{
  struct Object * newObj;
  
  newObj = PSObject_addDelegateNamed_valued_at_(obj, name, value, PSObject_totalSize((struct Object *) (obj -> map) -> delegates));
  if (newObj == Nil)
    return obj;
  
  return newObj;
}

struct Object * PSObject_addDelegateNamed_before_valued_(struct Object * obj, ObjectPointer name, ObjectPointer succ, ObjectPointer value)
{
  struct SlotEntry * entry;
  unsigned long int offset;
  struct Object * newObj;
  
  entry = PSSlotTable_hashEntryForName_((obj -> map) -> slotTable, succ);
  if (entry == Nil)
    return obj;
  offset = ObjectPointer_asSmallInt(entry -> offset);
  if (!((offset & SlotTypeMask) == SlotTypeDelegate))
    return obj;
  newObj = PSObject_addDelegateNamed_valued_at_(obj, name, value, offset & SlotOffsetMask);
  if (newObj == Nil)
    return obj;
  
  return newObj;
}

struct Object * PSObject_addDelegateNamed_after_valued_(struct Object * obj, ObjectPointer name, ObjectPointer pred, ObjectPointer value)
{
  struct SlotEntry * entry;
  unsigned long int offset;
  struct Object * newObj;
  
  entry = PSSlotTable_hashEntryForName_((obj -> map) -> slotTable, pred);
  if (entry == Nil)
    return obj;
  offset = ObjectPointer_asSmallInt(entry -> offset);
  if (!((offset & SlotTypeMask) == SlotTypeDelegate))
    return obj;
  newObj = PSObject_addDelegateNamed_valued_at_(obj, name, value, (unsigned long int) ((offset & SlotOffsetMask) + 4));
  if (newObj == Nil)
    return obj;
  
  return newObj;
}

struct Object * PSObject_removeSlotNamed_(struct Object * obj, ObjectPointer name)
{
  struct SlotEntry * entry;
  
  entry = PSSlotTable_hashEntryForName_((obj -> map) -> slotTable, name);
  if (entry == Nil)
    return obj;
  
  return (ObjectPointer_asSmallInt(entry -> offset) & SlotTypeMask) == SlotTypeDelegate?PSObject_removeDelegate_(obj, entry):PSObject_removeSlot_(obj, entry);
}

struct Object * PSObject_removeSlot_(struct Object * obj, struct SlotEntry * entry)
{
  struct Map * map;
  struct Object * newObj;
  unsigned long int offset;
  
  offset = ObjectPointer_asSmallInt(entry -> offset) & SlotOffsetMask;
  map = PSObjectHeap_cloneMap_(CurrentMemory, obj -> map);
  map -> slotCount = signedLongInt_asObject(ObjectPointer_asSmallInt(map -> slotCount) - 1);
  PSObjectHeap_rootStackPush_(CurrentMemory, (ObjectPointer *) (&map));
  map -> slotTable = PSSlotTable_growBy_excluding_(map -> slotTable, -1, entry -> name);
  PSSlotTable_relocateAll_above_by_(map -> slotTable, SlotTypeData, offset, -4);
  if ((obj -> header).objectFormat == FormatObject)
  {
    newObj = PSObjectHeap_allocateChunkSized_(CurrentMemory, (unsigned long int) ((obj -> header).objectSize - 1));
    (newObj -> header).objectFormat = (obj -> header).objectFormat;
  }
  else
    if ((obj -> header).objectSize == ObjectSizeMask)
      if (PSObject_payloadSize(obj) == 4)
      {
        newObj = PSObjectHeap_allocateChunkSized_(CurrentMemory, ObjectSizeMask);
        (newObj -> header).objectFormat = FormatObject;
      }
      else
      {
        newObj = PSObjectHeap_allocateChunkSized_withPayload_(CurrentMemory, ObjectSizeMask, (unsigned long int) (PSObject_payloadSize(obj) - 4));
        (newObj -> header).objectFormat = FormatOopArray;
      }
    else
    {
      newObj = PSObjectHeap_allocateChunkSized_withPayload_(CurrentMemory, (unsigned long int) ((obj -> header).objectSize - 1), PSObject_payloadSize(obj));
      (newObj -> header).objectFormat = (obj -> header).objectFormat;
    }
  PSObjectHeap_rootStackPop_(CurrentMemory, (unsigned long int) 1);
  (newObj -> header).objectFormat = (obj -> header).objectFormat;
  (newObj -> header).idHash = PSObjectHeap_newIdentityHash(CurrentMemory);
  PByte_copyBytes_into_((Byte *) obj + PSObject_firstSlotOffset(obj), offset - PSObject_firstSlotOffset(obj), (Byte *) newObj + PSObject_firstSlotOffset(newObj));
  PByte_copyBytes_into_(((Byte *) obj + offset) + 4, (unsigned long int) ((PSObject_totalSize(obj) - offset) - 4), (Byte *) newObj + offset);
  newObj -> map = map;
  map -> representative = PSObject_asObject(newObj);
  
  return newObj;
}

struct Object * PSObject_removeDelegate_(struct Object * obj, struct SlotEntry * entry)
{
  unsigned long int delsSize;
  unsigned long int pos;
  struct OopArray * newDels;
  struct OopArray * oldDels;
  struct Map * map;
  unsigned long int offset;
  
  offset = ObjectPointer_asSmallInt(entry -> offset) & SlotOffsetMask;
  map = PSObjectHeap_cloneMap_(CurrentMemory, obj -> map);
  PSObjectHeap_rootStackPush_(CurrentMemory, (ObjectPointer *) (&map));
  map -> slotTable = PSSlotTable_growBy_excluding_(map -> slotTable, -1, entry -> name);
  PSSlotTable_relocateAll_above_by_(map -> slotTable, SlotTypeDelegate, offset, -4);
  oldDels = map -> delegates;
  delsSize = PSObject_arraySize((struct Object *) oldDels);
  newDels = (struct OopArray *) PSObjectHeap_newOopArray_sized_(CurrentMemory, ArrayProto, (unsigned long int) (delsSize - 1));
  PSObjectHeap_rootStackPop_(CurrentMemory, (unsigned long int) 1);
  pos = (offset - PSObject_arrayOffset((struct Object *) oldDels)) / 4;
  PWord_copyWords_into_((Word *) oldDels -> elements, pos, (Word *) newDels -> elements);
  PWord_copyWords_into_(((Word *) oldDels -> elements + pos) + 1, (unsigned long int) ((delsSize - pos) - 1), (Word *) newDels -> elements + pos);
  map -> delegates = newDels;
  PSObject_changeMapTo_(obj, map);
  
  return obj;
}

Bool PSObject_addRoleNamed_at_dispatching_(struct Object * obj, ObjectPointer name, unsigned long int position, struct MethodDefinition * method)
{
  struct RoleEntry * entry;
  struct Map * map;
  struct RoleEntry * chain;
  
  map = PSObjectHeap_cloneMap_(CurrentMemory, obj -> map);
  chain = PSRoleTable_hashEntryForName_((obj -> map) -> roleTable, name);
  PSObject_makeRepresentativeOf_(obj, map);
  while (!(chain == Nil))
  {
    if (chain -> methodDefinition == method)
    {
      map -> roleTable = PSRoleTable_growBy_excluding_(map -> roleTable, 0, (struct MethodDefinition *) Nil);
      entry = PSRoleTable_hashEntryForName_(map -> roleTable, name);
      while (!(entry == Nil))
      {
        if (entry -> methodDefinition == method)
        {
          entry -> rolePositions = signedLongInt_asObject(ObjectPointer_asSmallInt(entry -> rolePositions) | position);
          
          return False;
        }
        if (entry -> nextRole == CurrentMemory -> NilObject)
          entry = Nil;
        else
          entry = &((map -> roleTable) -> roles)[ObjectPointer_asSmallInt(entry -> nextRole)];
      }
    }
    if (chain -> nextRole == CurrentMemory -> NilObject)
      chain = Nil;
    else
      chain = &((map -> roleTable) -> roles)[ObjectPointer_asSmallInt(chain -> nextRole)];
  }
  map -> roleTable = PSRoleTable_growBy_excluding_(map -> roleTable, 1, (struct MethodDefinition *) Nil);
  entry = PSRoleTable_hashEntryForInsertingName_(map -> roleTable, name);
  chain = PSRoleTable_hashEntryForName_(map -> roleTable, name);
  if (chain != Nil)
  {
    while (!(chain -> nextRole == CurrentMemory -> NilObject))
      chain = &((map -> roleTable) -> roles)[ObjectPointer_asSmallInt(chain -> nextRole)];
    chain -> nextRole = unsignedLongInt_asObject((unsigned long int) (entry - (map -> roleTable) -> roles));
  }
  entry -> name = name;
  entry -> nextRole = CurrentMemory -> NilObject;
  entry -> rolePositions = unsignedLongInt_asObject(position);
  entry -> methodDefinition = method;
  
  return True;
}

Bool PSObject_removeRoleNamed_dispatching_(struct Object * obj, ObjectPointer name, struct MethodDefinition * method)
{
  struct Map * map;
  unsigned long int n;
  struct RoleTable * roles;
  
  n = 0;
  roles = (obj -> map) -> roleTable;
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (PSRoleTable_capacity(roles) - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        if (((roles -> roles)[index]).methodDefinition == method)
          ++n;
      }
    }
  }
  if (n == 0)
    return False;
  map = PSObjectHeap_cloneMap_(CurrentMemory, obj -> map);
  map -> roleTable = PSRoleTable_growBy_excluding_(roles, (signed long int) n, method);
  PSObject_makeRepresentativeOf_(obj, map);
  
  return True;
}

struct MethodDefinition * PSObject_hasRoleNamed_at_dispatching_(struct Object * obj, unsigned long int selector, unsigned long int positions, ObjectPointer method)
{
  struct Map * map;
  
  map = obj -> map;
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (PSRoleTable_capacity(map -> roleTable) - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        struct RoleEntry * role;
        
        role = &((map -> roleTable) -> roles)[index];
        if (((role -> name == selector) && ((ObjectPointer_asSmallInt(role -> rolePositions) & positions) == positions)) && ((role -> methodDefinition) -> method == method))
          return role -> methodDefinition;
      }
    }
  }
  
  return Nil;
}

struct MethodDefinition * ObjectPointer_isMethod_on_arity_(ObjectPointer method, ObjectPointer selector, ObjectPointer * args, unsigned long int n)
{
  struct MethodDefinition * def;
  unsigned long int positions;
  
  positions = 0;
  def = Nil;
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (n - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        struct MethodDefinition * roleDef;
        ObjectPointer role;
        
        role = args[index];
        if (!(ObjectPointer_isSmallInt(role)))
        {
          struct Object * obj;
          
          obj = ObjectPointer_pointer(role);
          roleDef = PSObject_hasRoleNamed_at_dispatching_(obj, (unsigned long int) selector, (unsigned long int) (1 << index), method);
          if (roleDef != Nil)
          {
            positions = positions | (1 << index);
            def = roleDef;
          }
        }
      }
    }
  }
  
  return (def != Nil) && (positions == def -> dispatchPositions)?def:Nil;
}

struct MethodDefinition * ObjectPointer_asMethod_on_arity_(ObjectPointer method, ObjectPointer selector, ObjectPointer * args, unsigned long int n)
{
  struct MethodDefinition * oldDef;
  struct MethodDefinition * def;
  ObjectPointer argBuffer[16];
  unsigned long int positions;
  struct Symbol * sym;
  
  positions = 0;
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (n - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        ObjectPointer role;
        
        role = args[index];
        if (!(ObjectPointer_isSmallInt(role) || (role == PSObjectHeap_specialAt_(CurrentMemory, NoRoleObject))))
          positions = positions | (1 << index);
      }
    }
  }
  sym = (struct Symbol *) ObjectPointer_pointer(selector);
  sym -> cacheMask = signedLongInt_asObject(ObjectPointer_asSmallInt(sym -> cacheMask) | positions);
  PWord_copyWords_into_((Word *) args, n, (Word *) argBuffer);
  oldDef = ObjectPointer_dispatchTo_arity_above_(selector, (ObjectPointer *) argBuffer, n, (ObjectPointer) 0);
  if (!(((oldDef != Nil) && (oldDef -> dispatchPositions == positions)) && (oldDef == ObjectPointer_isMethod_on_arity_(oldDef -> method, selector, args, n))))
    oldDef = Nil;
  def = (struct MethodDefinition *) PSObjectHeap_cloneSpecial_(CurrentMemory, MethodDefinitionProto);
  PSObjectHeap_rootStackPush_(CurrentMemory, (ObjectPointer *) (&def));
  def -> method = method;
  def -> dispatchPositions = positions;
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (n - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        ObjectPointer role;
        
        role = args[index];
        if (!(ObjectPointer_isSmallInt(role) || (role == PSObjectHeap_specialAt_(CurrentMemory, NoRoleObject))))
        {
          struct Object * obj;
          
          obj = ObjectPointer_pointer(role);
          if (oldDef != Nil)
            PSObject_removeRoleNamed_dispatching_(obj, selector, oldDef);
          PSObject_addRoleNamed_at_dispatching_(obj, selector, (unsigned long int) (1 << index), def);
        }
      }
    }
  }
  PSObjectHeap_rootStackPop_(CurrentMemory, (unsigned long int) 1);
  
  return def;
}

void ObjectPointer_flushMethodCache(ObjectPointer selector)
{
  struct MethodCacheEntry * cacheEntry;
  unsigned long int n;
  
  if (selector == CurrentMemory -> NilObject)
  {
    PWord_fillWords_with_((Word *) methodCache, (unsigned long int) (MethodCacheSize * 5), (Word) Nil);
    
    {
      return;
    }
  }
  n = MethodCacheSize;
  cacheEntry = methodCache;
  while (n > 0)
  {
    if (cacheEntry -> selector == selector)
      cacheEntry -> selector = CurrentMemory -> NilObject;
    ++cacheEntry;
    --n;
  }
}

void PSMethodDefinition_cacheAs_on_arity_(struct MethodDefinition * def, ObjectPointer name, ObjectPointer * arguments, unsigned long int n)
{
  unsigned long int hash;
  
  hash = (name + ((ObjectPointer_checkMap(arguments[0])) -> header).idHash) & (MethodCacheSize - 1);
  (methodCache[hash]).method = def;
  (methodCache[hash]).selector = name;
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (n - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        ((methodCache[hash]).maps)[index] = ObjectPointer_checkMap(arguments[index]);
      }
    }
  }
}

struct MethodDefinition * ObjectPointer_dispatchTo_arity_above_(ObjectPointer name, ObjectPointer * arguments, unsigned long int n, ObjectPointer resendMethod)
{
  unsigned long int resendRank;
  struct MethodDefinition * dispatch;
  unsigned long int depth;
  unsigned long int bestRank;
  struct Object * slotLocation;
  signed long int restricted;
  struct MethodDefinition * bestDef;
  unsigned long int delegationCount;
  
  slotLocation = Nil;
  dispatch = resendMethod == 0?ObjectPointer_checkMethodCacheOn_(name, arguments):Nil;
  if (dispatch != Nil)
    return dispatch;
  currentDispatchID = currentDispatchID + 1;
  bestRank = 0;
  bestDef = Nil;
  resendRank = resendMethod == 0?~0:0;
  
  {
    unsigned long int _i_ = 0;
    unsigned long int _j_ = (n - 1) + 1;
    
    for (; _i_ < _j_; _i_+=1)
    {
      unsigned long int index = _i_;
      
      
      {
        ObjectPointer arg;
        
        delegationCount = 0;
        depth = 0;
        restricted = -1;
        arg = arguments[index];
        
        {
          struct Object * obj;
          struct Map * map;
          
          do
          {
            if (ObjectPointer_isSmallInt(arg))
              obj = ObjectPointer_pointer(PSObjectHeap_specialAt_(CurrentMemory, SmallIntegerProto));
            else
              obj = ObjectPointer_pointer(arg);
            map = obj -> map;
            if (!(map -> dispatchID == currentDispatchID))
            {
              map -> dispatchID = currentDispatchID;
              map -> visitedPositions = 0;
            }
            if (((map -> visitedPositions & (1 << index)) == 0) && (((map -> flags & MapFlagRestrictDelegation) == 0) || (restricted < 0)))
            {
              struct RoleEntry * role;
              
              if ((map -> flags & MapFlagRestrictDelegation) && (arg != arguments[index]))
                restricted = delegationCount;
              map -> visitedPositions = map -> visitedPositions | (1 << index);
              role = PSRoleTable_hashEntryForName_(map -> roleTable, name);
              if (role != Nil)
              {
                
                {
                  do
                  {
                    if ((ObjectPointer_asSmallInt(role -> rolePositions) & (1 << index)) != 0)
                    {
                      struct MethodDefinition * def;
                      
                      def = role -> methodDefinition;
                      if (!(def -> dispatchID == currentDispatchID))
                      {
                        def -> dispatchID = currentDispatchID;
                        def -> foundPositions = 0;
                        def -> dispatchRank = 0;
                      }
                      if ((def -> foundPositions & (1 << index)) == 0)
                      {
                        def -> dispatchRank = def -> dispatchRank | ((31 - depth) << ((5 - index) * 5));
                        def -> foundPositions = def -> foundPositions | (1 << index);
                        if (def -> method == resendMethod)
                        {
                          struct RoleEntry * rescan;
                          
                          resendRank = def -> dispatchRank;
                          rescan = PSRoleTable_hashEntryForName_(map -> roleTable, name);
                          while (!(rescan == role))
                          {
                            struct MethodDefinition * redef;
                            
                            redef = rescan -> methodDefinition;
                            if (((redef -> foundPositions == redef -> dispatchPositions) && ((dispatch == Nil) || (redef -> dispatchRank > dispatch -> dispatchRank))) && (redef -> dispatchRank <= resendRank))
                            {
                              dispatch = redef;
                              slotLocation = obj;
                              if (redef -> dispatchRank > bestRank)
                              {
                                bestRank = redef -> dispatchRank;
                                bestDef = redef;
                              }
                            }
                            if (rescan -> nextRole == CurrentMemory -> NilObject)
                              rescan = Nil;
                            else
                              rescan = &((map -> roleTable) -> roles)[ObjectPointer_asSmallInt(rescan -> nextRole)];
                          }
                        }
                        else
                          if (((def -> foundPositions == def -> dispatchPositions) && ((dispatch == Nil) || (def -> dispatchRank > dispatch -> dispatchRank))) && (def -> dispatchRank <= resendRank))
                          {
                            dispatch = def;
                            slotLocation = obj;
                            if (def -> dispatchRank > bestRank)
                            {
                              bestRank = def -> dispatchRank;
                              bestDef = def;
                            }
                          }
                        if ((def -> dispatchRank >= bestRank) && (def != bestDef))
                        {
                          bestRank = def -> dispatchRank;
                          bestDef = Nil;
                        }
                      }
                    }
                    role = role -> nextRole == CurrentMemory -> NilObject?Nil:&((map -> roleTable) -> roles)[ObjectPointer_asSmallInt(role -> nextRole)];
                  }
                  while (!(role == Nil));
                }
                if (depth > 31)
                  error("Dispatch exceeded maximum ordering depth.");
                if ((dispatch != Nil) && (bestDef == dispatch))
                {
                  if (!(dispatch -> slotAccessor == CurrentMemory -> NilObject))
                    arguments[0] = PSObject_asObject(slotLocation);
                  if ((resendMethod == 0) && (n <= MethodCacheArity))
                    PSMethodDefinition_cacheAs_on_arity_(dispatch, name, arguments, n);
                  
                  return dispatch;
                }
                ++depth;
              }
              if (PSObject_arraySize((struct Object *) map -> delegates) > 0)
              {
                struct OopArray * delegates;
                
                delegates = map -> delegates;
                
                {
                  unsigned long int _i_ = PSObject_arrayOffset((struct Object *) delegates);
                  unsigned long int _j_ = (PSObject_totalSize((struct Object *) delegates) - 4) + 4;
                  
                  for (; _i_ < _j_; _i_+=4)
                  {
                    unsigned long int offset = _i_;
                    
                    
                    {
                      ObjectPointer delegate;
                      
                      delegate = PSObject_slotValueAtOffset_((struct Object *) delegates, offset);
                      if (!(delegate == CurrentMemory -> NilObject))
                      {
                        delegationStack[delegationCount] = delegate;
                        ++delegationCount;
                      }
                    }
                  }
                }
              }
            }
            --delegationCount;
            if (delegationCount < DelegationStackSize)
            {
              arg = delegationStack[delegationCount];
              if ((signed long int) delegationCount < restricted)
                restricted = -1;
            }
          }
          while (delegationCount < DelegationStackSize);
        }
      }
    }
  }
  if (!((dispatch == Nil) || (dispatch -> slotAccessor == CurrentMemory -> NilObject)))
    arguments[0] = PSObject_asObject(slotLocation);
  if (((dispatch != Nil) && (resendMethod == 0)) && (n <= MethodCacheArity))
    PSMethodDefinition_cacheAs_on_arity_(dispatch, name, arguments, n);
  
  return dispatch;
}

void PSInterpreter_growStack(struct Interpreter * i)
{
  struct OopArray * newStack;
  
  i -> stackSize = i -> stackSize * 2;
  newStack = (struct OopArray *) PSObjectHeap_newOopArray_sized_(CurrentMemory, ArrayProto, i -> stackSize);
  PWord_copyWords_into_((Word *) (i -> stack) -> elements, i -> stackPointer, (Word *) newStack -> elements);
  i -> stack = newStack;
}

void PSInterpreter_signal_on_arity_withOptionals_(struct Interpreter * i, unsigned long int signalIndex, ObjectPointer * args, unsigned long int n, struct OopArray * opts)
{
  struct MethodDefinition * def;
  ObjectPointer selector;
  struct Closure * method;
  
  selector = PSObjectHeap_specialAt_(CurrentMemory, signalIndex);
  def = ObjectPointer_dispatchTo_arity_above_(selector, args, n, (ObjectPointer) 0);
  if (def == Nil)
    unhandledSignal(selector, n, args);
  method = (struct Closure *) ObjectPointer_pointer(def -> method);
  PSInterpreter_apply_to_arity_withOptionals_(i, method, args, n, opts);
}

void PSInterpreter_signal_with_(struct Interpreter * i, unsigned long int signalIndex, ObjectPointer x)
{
  ObjectPointer args[1];
  
  args[0] = x;
  PSInterpreter_signal_on_arity_withOptionals_(i, signalIndex, (ObjectPointer *) args, (unsigned long int) 1, (struct OopArray *) Nil);
}

void PSInterpreter_signal_with_with_(struct Interpreter * i, unsigned long int signalIndex, ObjectPointer x, ObjectPointer y)
{
  ObjectPointer args[2];
  
  args[0] = x;
  args[1] = y;
  PSInterpreter_signal_on_arity_withOptionals_(i, signalIndex, (ObjectPointer *) args, (unsigned long int) 2, (struct OopArray *) Nil);
}

void PSInterpreter_signal_with_with_with_(struct Interpreter * i, unsigned long int signalIndex, ObjectPointer x, ObjectPointer y, ObjectPointer z)
{
  ObjectPointer args[3];
  
  args[0] = x;
  args[1] = y;
  args[2] = z;
  PSInterpreter_signal_on_arity_withOptionals_(i, signalIndex, (ObjectPointer *) args, (unsigned long int) 3, (struct OopArray *) Nil);
}

void PSInterpreter_dispatchOptionals_(struct Interpreter * i, struct OopArray * opts)
{
  unsigned long int index;
  unsigned long int optsSize;
  
  optsSize = PSObject_arraySize((struct Object *) opts);
  index = 0;
  while (index < optsSize)
  {
    PSInterpreter_dispatchOptionalKeyword_valued_(i, (opts -> elements)[index], (opts -> elements)[index + 1]);
    index+=2;
  }
}

void PSInterpreter_send_to_through_arity_withOptionals_(struct Interpreter * i, ObjectPointer selector, ObjectPointer * args, ObjectPointer * dispatchers, unsigned long int n, struct OopArray * opts)
{
  struct OopArray * argsArray;
  struct MethodDefinition * def;
  ObjectPointer traitsWindow;
  struct Closure * method;
  
  #ifdef DEBUG_MSG
  printSymbol(stderr, selector); fputc('\n', stderr);
#endif
;
  def = ObjectPointer_dispatchTo_arity_above_(selector, dispatchers, n, (ObjectPointer) 0);
  if (def == Nil)
  {
    argsArray = (struct OopArray *) PSObjectHeap_newOopArray_sized_(CurrentMemory, ArrayProto, n);
    PWord_copyWords_into_((Word *) dispatchers, n, (Word *) argsArray -> elements);
    
    {
      PSInterpreter_signal_with_with_(i, NotFoundOnSymbol, selector, PSObject_asObject((struct Object *) argsArray));
      
      return;
    }
  }
  method = (struct Closure *) ObjectPointer_pointer(def -> method);
  traitsWindow = (((method -> map) -> delegates) -> elements)[0];
  if (traitsWindow == CurrentMemory -> PrimitiveMethodWindow)
    (primitives[ObjectPointer_asSmallInt(((struct PrimitiveMethod *) method) -> index)])(i, args, n, opts);
  else
    if ((traitsWindow == CurrentMemory -> CompiledMethodWindow) || (traitsWindow == CurrentMemory -> ClosureWindow))
      PSInterpreter_apply_to_arity_withOptionals_(i, method, args, n, opts);
    else
    {
      struct OopArray * optsArray;
      ObjectPointer signalArgs[2];
      
      argsArray = (struct OopArray *) PSObjectHeap_newOopArray_sized_(CurrentMemory, ArrayProto, n);
      PWord_copyWords_into_((Word *) args, n, (Word *) argsArray -> elements);
      signalArgs[0] = def -> method;
      signalArgs[1] = PSObject_asObject((struct Object *) argsArray);
      if (opts == Nil)
        optsArray = Nil;
      else
      {
        optsArray = (struct OopArray *) PSObjectHeap_newOopArray_sized_(CurrentMemory, ArrayProto, (unsigned long int) 2);
        (optsArray -> elements)[0] = PSObjectHeap_specialAt_(CurrentMemory, OptionalsSymbol);
        (optsArray -> elements)[1] = PSObject_asObj