VM Maker: VMMaker.oscog-eem.2299.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

VM Maker: VMMaker.oscog-eem.2299.mcz

commits-2
 
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2299.mcz

==================== Summary ====================

Name: VMMaker.oscog-eem.2299
Author: eem
Time: 21 December 2017, 9:17:52.747344 pm
UUID: 53b6a352-dbde-430a-9ec1-cb56154fe2c5
Ancestors: VMMaker.oscog-eem.2298

Get the StackInterpreterSimulator to a state where it can correctly simulate the DoubleByteArray, WordArray, DoubleWordArray and MemoryTests.  Principally allow the SqueakFFIPrims plugin (ThreadedFFIPlugin) to load and make primitiveFFIIntegerAt[Put] function correctly in simulation.  Change the two primitives to use unalignedShortAt:[put:], unalignedLong32At:[put:] & unalignedLong64At:[put:] and implement these in SpurMemoryManager (ObjectMemory can wait) and have the preambleCCode map these to the original shortAt[put],  long32At[put] & long32At[put] C functions/macros.

Fix a bug in the simulation of LargeIntegersPlugin>>cDigitSub:len:with:len:into: (Nicolas, there may be similar signedness issues in other functions.  If you have time and energy please consider taking a look at the code in the simulator).

Fix a slip in the range comparison for 64-bit integer arguments in genPrimitiveAtPut.

=============== Diff against VMMaker.oscog-eem.2298 ===============

Item was added:
+ ----- Method: CoInterpreter>>ISA (in category 'simulation') -----
+ ISA
+ <doNotGenerate>
+ ^cogit backEnd class ISA!

Item was changed:
  ----- Method: CogClass>>cCoerceSimple:to: (in category 'translation support') -----
  cCoerceSimple: value to: cTypeString
  <doNotGenerate>
  "Type coercion for translation and simulation.
  For simulation answer a suitable surrogate for the struct types"
  ^cTypeString caseOf:
    { [#'unsigned long'] -> [value].
  [#'unsigned int'] -> [value].
+ [#'unsigned short'] -> [value].
+ [#sqInt] -> [value].
- [#sqInt] -> [value].
  [#'sqIntptr_t'] -> [value].
  [#'usqIntptr_t'] -> [value].
  [#usqInt] -> [value].
  [#sqLong] -> [value].
+ [#usqLong] -> [value].
- [#usqLong] -> [value].
  [#'AbstractInstruction *'] -> [value].
  [#'BytecodeFixup *'] -> [value].
  [#'CogMethod *'] -> [value].
  [#'char *'] -> [value].
  [#'sqInt *'] -> [value].
  [#'void *'] -> [value].
  [#void] -> [value].
  [#'void (*)()'] -> [value].
  [#'void (*)(void)'] -> [value].
  [#'unsigned long (*)(void)'] -> [value].
  [#'void (*)(unsigned long,unsigned long)'] -> [value].
  [#'usqIntptr_t (*)(void)'] -> [value] }!

Item was changed:
  ----- Method: CogObjectRepresentationFor64BitSpur>>genPrimitiveAtPut (in category 'primitive generators') -----
(excessive size, no diff calculated)

Item was changed:
  ----- Method: FFIPlugin class>>moduleName (in category 'translation') -----
  moduleName "FFIPlugin translate"
  "IMPORTANT: IF YOU CHANGE THE NAME OF THIS PLUGIN YOU MUST CHANGE
  Interpreter>>primitiveCalloutToFFI
  TO REFLECT THE CHANGE."
+ ^'SqueakFFIPrims (Obsolete)'!
- ^'SqueakFFIPrims'!

Item was changed:
  ----- Method: FilePluginSimulator>>sqFileDeleteName:Size: (in category 'simulation') -----
  sqFileDeleteName: nameIndex Size: nameSize
  | path |
+ path := interpreterProxy asString: nameIndex size: nameSize.
- path := interpreterProxy interpreter asString: nameIndex size: nameSize.
  (StandardFileStream isAFileNamed: path) ifFalse:
  [^interpreterProxy primitiveFail].
  [FileDirectory deleteFilePath: path]
  on: Error
  do: [:ex| interpreterProxy primitiveFail]!

Item was changed:
  ----- Method: LargeIntegersPlugin>>cDigitSub:len:with:len:into: (in category 'C core') -----
  cDigitSub: pWordSmall
  len: smallLen
  with: pWordLarge
  len: largeLen
  into: pWordRes
  | z |
  <var: #pWordSmall type: #'unsigned int *'>
  <var: #pWordLarge type: #'unsigned int *'>
  <var: #pWordRes type: #'unsigned int *'>
  <var: #z type: #'unsigned long long'>
 
  z := 0.
  0 to: smallLen - 1 do:
  [:i |
  z := z + (self cDigitOf: pWordLarge at: i) - (self cDigitOf: pWordSmall at: i).
  self cDigitOf: pWordRes at: i put: (z bitAnd: 16rFFFFFFFF).
+ z := 0 - (self cCode: [z >> 63] inSmalltalk: [z >> 63 bitAnd: 1])].
- z := 0 - (z >> 63)].
  smallLen to: largeLen - 1 do:
  [:i |
  z := z + (self cDigitOf: pWordLarge at: i) .
  self cDigitOf: pWordRes at: i put: (z bitAnd: 16rFFFFFFFF).
+ z := 0 - (self cCode: [z >> 63] inSmalltalk: [z >> 63 bitAnd: 1])].
- z := 0 - (z >> 63)].
  ^0!

Item was changed:
  ----- Method: Spur64BitMMLECoSimulatorFor64Bits>>long64At: (in category 'memory access') -----
  long64At: byteAddress
+ "memory is a DoubleWordArray, a 64-bit indexable array of bits"
- "memory is a DobleWordArray, a 64-bit indexable array of bits"
  byteAddress \\ 8 ~= 0 ifTrue: [self unalignedAccessError].
  ^memory at: byteAddress // 8 + 1!

Item was changed:
  ----- Method: Spur64BitMMLECoSimulatorFor64Bits>>long64At:put: (in category 'memory access') -----
  long64At: byteAddress put: a64BitValue
+ "memory is a DoubleWordArray, a 64-bit indexable array of bits"
- "memory is a DobleWordArray, a 64-bit indexable array of bits"
  byteAddress \\ 8 ~= 0 ifTrue: [self unalignedAccessError].
  ^memory at: byteAddress // 8 + 1 put: a64BitValue!

Item was changed:
  ----- Method: Spur64BitMMLESimulatorFor64Bits>>long32At:put: (in category 'memory access') -----
  long32At: byteAddress put: a32BitValue
    "Store the 32-bit word at byteAddress which must be a multiple of four."
  | lowBits long longAddress |
+ a32BitValue < 0 ifTrue:
+ [self long32At: byteAddress put: (a32BitValue bitAnd: 16rFFFFFFFF).
+ ^a32BitValue].
  lowBits := byteAddress bitAnd: 4.
  lowBits = 0
  ifTrue: "storing into LS word"
  [long := self long64At: byteAddress.
  self long64At: byteAddress
  put: ((long bitAnd: 16rFFFFFFFF00000000) bitOr: a32BitValue)]
  ifFalse: "storing into MS word"
  [longAddress := byteAddress - 4.
  long := self long64At: longAddress.
  self long64At: longAddress
  put: ((long bitAnd: 16rFFFFFFFF) bitOr: (a32BitValue bitShift: 32))].
  ^a32BitValue!

Item was changed:
  ----- Method: Spur64BitMMLESimulatorFor64Bits>>long64At:put: (in category 'memory access') -----
  long64At: byteAddress put: a64BitValue
+ "memory is a DoubleWordArray, a 64-bit indexable array of bits"
- "memory is a DobleWordArray, a 64-bit indexable array of bits"
  byteAddress \\ 8 ~= 0 ifTrue: [self unalignedAccessError].
  ^memory at: byteAddress // 8 + 1 put: a64BitValue!

Item was added:
+ ----- Method: SpurMemoryManager>>ISA (in category 'simulation only') -----
+ ISA
+ "hack around the CoInterpreter/ObjectMemory split refactoring"
+ <doNotGenerate>
+ ^coInterpreter ISA!

Item was added:
+ ----- Method: SpurMemoryManager>>signed64BitIntegerFor: (in category 'simulation only') -----
+ signed64BitIntegerFor: integerValue
+ "hack around the CoInterpreter/ObjectMemory split refactoring"
+ <doNotGenerate>
+ ^coInterpreter signed64BitIntegerFor: integerValue!

Item was added:
+ ----- Method: SpurMemoryManager>>signed64BitValueOf: (in category 'simulation only') -----
+ signed64BitValueOf: oop
+ "hack around the CoInterpreter/ObjectMemory split refactoring"
+ <doNotGenerate>
+ ^coInterpreter signed64BitValueOf: oop!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedLong32At: (in category 'simulation') -----
+ unalignedLong32At: index
+ "Support for primitiveFFIIntegerAt[Put]"
+ <doNotGenerate>
+ | odd hi lo |
+ (odd := index bitAnd: 3) = 0 ifTrue:
+ [^self long32At: index].
+ lo := self long32At: index - odd.
+ hi := self long32At: index + 4 - odd.
+ ^lo >> (odd * 8) + ((hi bitAnd: 1 << (odd * 8) - 1) << (4 - odd * 8))!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedLong32At:put: (in category 'simulation') -----
+ unalignedLong32At: index put: aValue
+ "Support for primitiveFFIIntegerAt[Put]"
+ <doNotGenerate>
+ | odd hi lo mask |
+ aValue < 0 ifTrue:
+ [self unalignedLong64At: index put: (aValue bitAnd: 16rFFFFFFFF).
+ ^aValue].
+ (odd := index bitAnd: 3) = 0 ifTrue:
+ [^self long32At: index put: aValue].
+ mask := 1 << (odd * 8) - 1.
+ lo := self long32At: index - odd.
+ self long32At: index - odd
+ put: (lo bitAnd: mask)
+ + ((aValue bitAnd: 1 << (4 - odd * 8) - 1) << (odd * 8)).
+ hi := self long32At: index + 4 - odd.
+ self long32At: index + 4 - odd
+ put: (hi bitClear: mask) + (aValue >> (4 - odd * 8) bitAnd: mask).
+ ^aValue!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedLong64At: (in category 'simulation') -----
+ unalignedLong64At: index
+ "Support for primitiveFFIIntegerAt[Put]"
+ <doNotGenerate>
+ | odd hi lo |
+ (odd := index bitAnd: 7) = 0 ifTrue:
+ [^self long64At: index].
+ lo := self long64At: index - odd.
+ hi := self long64At: index + 8 - odd.
+ ^lo >> (odd * 8) + ((hi bitAnd: 1 << (odd * 8) - 1) << (8 - odd * 8))!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedLong64At:put: (in category 'simulation') -----
+ unalignedLong64At: index put: aValue
+ "Support for primitiveFFIIntegerAt[Put]"
+ <doNotGenerate>
+ | odd hi lo mask |
+ aValue < 0 ifTrue:
+ [self unalignedLong64At: index put: (aValue bitAnd: 16rFFFFFFFFFFFFFFFF).
+ ^aValue].
+ (odd := index bitAnd: 7) = 0 ifTrue:
+ [^self long64At: index put: aValue].
+ mask := 1 << (odd * 8) - 1.
+ lo := self long64At: index - odd.
+ self long64At: index - odd
+ put: (lo bitAnd: mask)
+ + ((aValue bitAnd: 1 << (8 - odd * 8) - 1) << (odd * 8)).
+ hi := self long64At: index + 8 - odd.
+ self long64At: index + 8 - odd
+ put: (hi bitClear: mask) + (aValue >> (8 - odd * 8) bitAnd: mask).
+ ^aValue!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedShortAt: (in category 'simulation') -----
+ unalignedShortAt: index
+ "Support for primitiveFFIIntegerAt[Put]"
+ <doNotGenerate>
+ | hi lo |
+ (index bitAnd: 1) = 0 ifTrue:
+ [^self shortAt: index].
+ lo := self shortAt: index - 1.
+ hi := self shortAt: index + 1.
+ ^lo >> 8 + ((hi bitAnd: 16rFF) << 8)!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedShortAt:put: (in category 'simulation') -----
+ unalignedShortAt: index put: aValue
+ "Support for primitiveFFIIntegerAt[Put]"
+ <doNotGenerate>
+ (index bitAnd: 1) = 0 ifTrue:
+ [^self shortAt: index put: aValue].
+ self shouldBeImplemented.
+ ^aValue!

Item was added:
+ ----- Method: StackInterpreter>>ISA (in category 'simulation') -----
+ ISA
+ <doNotGenerate>
+ ^self class initializationOptions
+ at: #ISA
+ ifAbsent: [Smalltalk wordSize = 8
+ ifTrue: [#X64]
+ ifFalse: [#IA32]]!

Item was changed:
  ----- Method: StackInterpreter>>ioLoadExternalFunction:OfLength:FromModule:OfLength:AccessorDepthInto: (in category 'primitive support') -----
  ioLoadExternalFunction: functionName OfLength: functionLength FromModule: moduleName OfLength: moduleLength AccessorDepthInto: accessorDepthPtr
  "Load and return the requested function from a module.  Assign the accessor depth through accessorDepthPtr.
  N.B. The actual code lives in platforms/Cross/vm/sqNamedPrims.h"
  <doNotGenerate>
  | pluginString functionString |
  pluginString := String new: moduleLength.
+ (1 to: moduleLength) do:[:i| pluginString byteAt: i put: (objectMemory byteAt: moduleName+i-1)].
- 1 to: moduleLength do:[:i| pluginString byteAt: i put: (objectMemory byteAt: moduleName+i-1)].
  functionString := String new: functionLength.
+ (1 to: functionLength) do:[:i| functionString byteAt: i put: (objectMemory byteAt: functionName+i-1)].
+ "We used to ignore loads of the SqueakFFIPrims plugin, but that means doing without integerAt:[put:]size:signed:
+ which is too much of a limitation (not that these simulate unaligned accesses yet)."
- 1 to: functionLength do:[:i| functionString byteAt: i put: (objectMemory byteAt: functionName+i-1)].
- "Pharo images as of 2016 use the FFI plugin (for getenv:?).  We can't simulate such function loads.  So ignore"
- pluginString = 'SqueakFFIPrims' ifTrue:
- ["self halt."
- true ifTrue:
- [self transcript cr; show: 'ignoring function load from SqueakFFIPrims'.
- ^0]].
  ^self ioLoadFunction: functionString From: pluginString AccessorDepthInto: accessorDepthPtr!

Item was changed:
  ----- Method: ThreadedFFIPlugin class>>preambleCCode (in category 'translation') -----
  preambleCCode
  "For a source of builtin defines grep for builtin_define in a gcc release config directory."
  ^'
  #include "sqAssert.h" /* for assert */
  #define ThreadedFFIPlugin 1 /* to filter-out unwanted declarations from sqFFI.h */
  #include "sqFFI.h" /* for logging and surface functions */
  #include "sqCogStackAlignment.h" /* for STACK_ALIGN_BYTES and getsp() */
 
  #ifdef _MSC_VER
  # define alloca _alloca
  #endif
  #if defined(__GNUC__) && (defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__))
  # define setsp(sp) asm volatile ("movl %0,%%esp" : : "m"(sp))
  # elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__) ||  defined(__amd64) || defined(__x86_64))
  # define setsp(sp) asm volatile ("movq %0,%%rsp" : : "m"(sp))
  # elif defined(__GNUC__) && (defined(__arm__))
  # define setsp(sp) asm volatile ("ldr %%sp, %0" : : "m"(sp))
  #endif
  #if !!defined(getsp)
  # define getsp() 0
  #endif
  #if !!defined(setsp)
  # define setsp(ignored) 0
  #endif
 
  #if !!defined(STACK_ALIGN_BYTES)
  #  define STACK_ALIGN_BYTES 0
  #endif /* !!defined(STACK_ALIGN_BYTES) */
 
  /* For ABI that require stack alignment greater than natural word size */
  #define MUST_ALIGN_STACK (STACK_ALIGN_BYTES > sizeof(void*))
 
  #if defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__)
  /* Both Mac OS X x86 and Win32 x86 return structs of a power of two in size
   * less than or equal to eight bytes in length in registers. Linux never does so.
   */
  # if __linux__
  # define WIN32_X86_STRUCT_RETURN 0
  # else
  # define WIN32_X86_STRUCT_RETURN 1
  # endif
  # if _WIN32
  # define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 1
  # endif
  # elif defined(__amd64__) || defined(__x86_64__) ||  defined(__amd64) || defined(__x86_64)
  # if _WIN32 | _WIN64
  # define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 1
  # endif
  #endif /* defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) */
 
  #if !!defined(ALLOCA_LIES_SO_SETSP_BEFORE_CALL)
  # if defined(__MINGW32__) && !!defined(__clang__) && (__GNUC__ >= 3) && (defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__))
      /*
       * cygwin -mno-cygwin (MinGW) gcc 3.4.x''s alloca is a library routine that answers
       * %esp + xx, so the outgoing stack is offset by one or more word if uncorrected.
       * Grab the actual stack pointer to correct.
       */
  # define ALLOCA_LIES_SO_SETSP_BEFORE_CALL 1
  # else
  # define ALLOCA_LIES_SO_SETSP_BEFORE_CALL 0
  # endif
  #endif /* !!defined(ALLOCA_LIES_SO_SETSP_BEFORE_CALL) */
 
  #if !!defined(PLATFORM_API_USES_CALLEE_POPS_CONVENTION)
  # define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 0
  #endif
 
+ /* This alignment stuff is a hack for integerAt:put:size:signed:/primitiveFFIIntegerAt[Put].
+  * The assumption right now is that all processors suppoprt unaligned access.  That only
+  * holds true for x86, x86-64 & ARMv6 & later.  But this keeps us going until we can addresws it properly.
+  */
+ #define unalignedShortAt(a) shortAt(a)
+ #define unalignedShortAtput(a) shortAtput(a)
+ #define unalignedLong32At(a) long32At(a)
+ #define unalignedLong32Atput(a) long32Atput(a)
+ #define unalignedLong64At(a) long64At(a)
+ #define unalignedLong64Atput(a) long64Atput(a)
+
  /* The dispatchOn:in:with:with: generates an unwanted call on error.  Just squash it. */
  #define error(foo) 0
  #ifndef SQUEAK_BUILTIN_PLUGIN
  /* but print assert failures. */
  void
  warning(char *s) { /* Print an error message but don''t exit. */
  printf("\n%s\n", s);
  }
  #endif
 
  /* sanitize */
  #ifdef SQUEAK_BUILTIN_PLUGIN
  # define EXTERN
  #else
  # define EXTERN extern
  #endif
  '!

Item was added:
+ ----- Method: ThreadedFFIPlugin>>initSurfacePluginFunctionPointers (in category 'simulation') -----
+ initSurfacePluginFunctionPointers
+ "This is a simulation-only stub.  The real code is in
+ platforms/Cross/plugins/SqueakFFIPrims/sqManualSurface.c"
+ <doNotGenerate>!

Item was changed:
  ----- Method: ThreadedFFIPlugin>>initialiseModule (in category 'initialize') -----
  initialiseModule
  <export: true>
  "By default, disable logging"
  ffiLogEnabled := false.
  "Get the instSize of ExternalFunction to know whether it contains a cache of the stackSize,
  and what the offset of ExternalLibraryFunction's functionName and moduleName slots are."
  externalFunctionInstSize := interpreterProxy instanceSizeOf: interpreterProxy classExternalFunction.
  self initSurfacePluginFunctionPointers.
+ ^true!
- ^1!

Item was added:
+ ----- Method: ThreadedFFIPlugin>>morphIntoConcreteSubclass: (in category 'simulation') -----
+ morphIntoConcreteSubclass: aCoInterpreter
+ <doNotGenerate>
+ | concreteClass |
+ concreteClass :=
+ aCoInterpreter ISA caseOf: {
+ [#X64] -> [(Smalltalk platformName beginsWith: 'Win')
+ ifTrue: [ThreadedX64Win64FFIPlugin]
+ ifFalse: [ThreadedX64SysVFFIPlugin]].
+ [#IA32] -> [ThreadedIA32FFIPlugin].
+ [#ARMv5] -> [ThreadedARMFFIPlugin] }
+ otherwise: [self error: 'simulation not set up for this ISA'].
+ self changeClassTo: concreteClass!

Item was changed:
  ----- Method: ThreadedFFIPlugin>>primitiveFFIIntegerAt (in category 'primitives') -----
  primitiveFFIIntegerAt
  "Answer a (signed or unsigned) n byte integer from the given byte offset
  in the receiver, using the platform's endianness."
  | isSigned byteSize byteOffset rcvr addr value mask valueOop |
  <var: 'value' type: #usqLong>
  <var: 'mask' type: #usqLong>
  <export: true>
  <inline: false>
  isSigned := interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0).
  byteSize := interpreterProxy stackIntegerValue: 1.
  byteOffset := interpreterProxy stackIntegerValue: 2.
  rcvr := interpreterProxy stackObjectValue: 3.
  interpreterProxy failed ifTrue:[^0].
  (byteOffset > 0
  and: [(byteSize between: 1 and: 8)
  and: [(byteSize bitAnd: byteSize - 1) = 0 "a.k.a. isPowerOfTwo"]]) ifFalse:
  [^interpreterProxy primitiveFail].
  addr := self ffiAddressOf: rcvr startingAt: byteOffset size: byteSize.
  interpreterProxy failed ifTrue:[^0].
  byteSize <= 2
  ifTrue:
  [byteSize = 1
  ifTrue: [value := self cCoerceSimple: (interpreterProxy byteAt: addr) to: #'unsigned char']
+ ifFalse: [value := self cCoerceSimple: (interpreterProxy unalignedShortAt: addr) to: #'unsigned short']]
- ifFalse: [value := self cCoerceSimple: (interpreterProxy shortAt: addr) to: #'unsigned short']]
  ifFalse:
  [byteSize = 4
+ ifTrue: [value := self cCoerceSimple: (interpreterProxy unalignedLong32At: addr) to: #'unsigned int']
+ ifFalse: [value := interpreterProxy unalignedLong64At: addr]].
- ifTrue: [value := self cCoerceSimple: (interpreterProxy long32At: addr) to: #'unsigned int']
- ifFalse: [value := interpreterProxy long64At: addr]].
  byteSize < BytesPerWord
  ifTrue:
  [isSigned ifTrue: "sign extend value"
  [mask := 1 asUnsignedLongLong << (byteSize * 8 - 1).
  value := (value bitAnd: mask-1) - (value bitAnd: mask)].
  "note: byte/short (&long if BytesPerWord=8) never exceed SmallInteger range"
  valueOop := interpreterProxy integerObjectOf: value]
  ifFalse: "general 64 bit integer; note these never fail"
  [isSigned
  ifTrue:
  [byteSize < 8 ifTrue: "sign extend value"
  [mask := 1 asUnsignedLongLong << (byteSize * 8 - 1).
  value := (value bitAnd: mask-1) - (value bitAnd: mask)].
+ self cCode: [] inSmalltalk:
+ [(byteSize = 8 and: [(value bitShift: -56) >= 128]) ifTrue:
+ [value := value - (1 bitShift: 64)]].
  valueOop := interpreterProxy signed64BitIntegerFor: value]
  ifFalse:[valueOop := interpreterProxy positive64BitIntegerFor: value]].
  ^interpreterProxy pop: 4 thenPush: valueOop!

Item was changed:
  ----- Method: ThreadedFFIPlugin>>primitiveFFIIntegerAtPut (in category 'primitives') -----
  primitiveFFIIntegerAtPut
  "Store a (signed or unsigned) n byte integer at the given byte offset
  in the receiver, using the platform's endianness."
  | isSigned byteSize byteOffset rcvr addr value max valueOop |
  <var: 'value' type: #sqLong>
  <var: 'max' type: #sqLong>
  <export: true>
  <inline: false>
  isSigned := interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0).
  byteSize := interpreterProxy stackIntegerValue: 1.
  valueOop := interpreterProxy stackValue: 2.
  byteOffset := interpreterProxy stackIntegerValue: 3.
  rcvr := interpreterProxy stackObjectValue: 4.
  interpreterProxy failed ifTrue:[^0].
  (byteOffset > 0
  and: [(byteSize between: 1 and: 8)
  and: [(byteSize bitAnd: byteSize - 1) = 0 "a.k.a. isPowerOfTwo"]]) ifFalse:
  [^interpreterProxy primitiveFail].
  addr := self ffiAddressOf: rcvr startingAt: byteOffset size: byteSize.
  interpreterProxy failed ifTrue:[^0].
  isSigned
  ifTrue:[value := interpreterProxy signed64BitValueOf: valueOop]
  ifFalse:[value := interpreterProxy positive64BitValueOf: valueOop].
  interpreterProxy failed ifTrue:[^0].
  byteSize < 8 ifTrue:
  [isSigned
  ifTrue:
  [max := 1 asUnsignedLongLong << (8 * byteSize - 1).
  (value >= (0 - max) and: [value < max]) ifFalse: [^interpreterProxy primitiveFail]]
  ifFalse:
  [value asUnsignedLongLong < (1 asUnsignedLongLong << (8 * byteSize)) ifFalse: [^interpreterProxy primitiveFail]]].
  byteSize <= 2
  ifTrue:
  [byteSize = 1
  ifTrue: [interpreterProxy byteAt: addr put: value]
+ ifFalse: [interpreterProxy unalignedShortAt: addr put: value]]
- ifFalse: [interpreterProxy shortAt: addr put: value]]
  ifFalse:
  [byteSize = 4
+ ifTrue: [interpreterProxy unalignedLong32At: addr put: value]
+ ifFalse: [interpreterProxy unalignedLong64At: addr put: value]].
- ifTrue: [interpreterProxy long32At: addr put: value]
- ifFalse: [interpreterProxy long64At: addr put: value]].
  ^interpreterProxy pop: 5 thenPush: valueOop!

Item was added:
+ ----- Method: ThreadedFFIPlugin>>setInterpreter: (in category 'simulation') -----
+ setInterpreter: anInterpreter
+ "Initialization of the plugin in the simulator.
+ The real routine is in the superclass."
+ self cCode: []
+ inSmalltalk: [self class == thisContext method methodClass ifTrue:
+ [self morphIntoConcreteSubclass: anInterpreter]].
+ ^super setInterpreter: anInterpreter!

Reply | Threaded
Open this post in threaded view
|

Re: VM Maker: VMMaker.oscog-eem.2299.mcz

Nicolas Cellier
 
Hi Eliot,
if we have a certified arithmetic right shift that preserves integer kind
- not something like (((usqint) x) >> 32), which is a logical right shift
- nor (((sqint) x) >> 32)
then what we could do is use a signed long long to store intermediate result:
(I call it arithmeticRightShift: because I don't have a VMMaker handy to verify the right name
maybe it was >>> ? but then that's the reverse meaning of java!)

        <var: #pWordSmall type: #'unsigned int *'>
        <var: #pWordLarge type: #'unsigned int *'>
        <var: #pWordRes type: #'unsigned int *'>
        <var: #z type: #'long long'>

        z := 0.
        0 to: smallLen - 1 do:
                [:i |
                z := z + (self cDigitOf: pWordLarge at: i) - (self cDigitOf: pWordSmall at: i).
                self cDigitOf: pWordRes at: i put: (z bitAnd: 16rFFFFFFFF).
                z := z arithmeticRightShift: 32].
        smallLen to: largeLen - 1 do:
                [:i |
                z := z + (self cDigitOf: pWordLarge at: i).
                self cDigitOf: pWordRes at: i put: (z bitAnd: 16rFFFFFFFF).
                z := z arithmeticRightShift: 32].
        ^0!

2017-12-22 6:18 GMT+01:00 <[hidden email]>:

Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2299.mcz

==================== Summary ====================

Name: VMMaker.oscog-eem.2299
Author: eem
Time: 21 December 2017, 9:17:52.747344 pm
UUID: 53b6a352-dbde-430a-9ec1-cb56154fe2c5
Ancestors: VMMaker.oscog-eem.2298

Get the StackInterpreterSimulator to a state where it can correctly simulate the DoubleByteArray, WordArray, DoubleWordArray and MemoryTests.  Principally allow the SqueakFFIPrims plugin (ThreadedFFIPlugin) to load and make primitiveFFIIntegerAt[Put] function correctly in simulation.  Change the two primitives to use unalignedShortAt:[put:], unalignedLong32At:[put:] & unalignedLong64At:[put:] and implement these in SpurMemoryManager (ObjectMemory can wait) and have the preambleCCode map these to the original shortAt[put],  long32At[put] & long32At[put] C functions/macros.

Fix a bug in the simulation of LargeIntegersPlugin>>cDigitSub:len:with:len:into: (Nicolas, there may be similar signedness issues in other functions.  If you have time and energy please consider taking a look at the code in the simulator).

Fix a slip in the range comparison for 64-bit integer arguments in genPrimitiveAtPut.

=============== Diff against VMMaker.oscog-eem.2298 ===============

Item was added:
+ ----- Method: CoInterpreter>>ISA (in category 'simulation') -----
+ ISA
+       <doNotGenerate>
+       ^cogit backEnd class ISA!

Item was changed:
  ----- Method: CogClass>>cCoerceSimple:to: (in category 'translation support') -----
  cCoerceSimple: value to: cTypeString
        <doNotGenerate>
        "Type coercion for translation and simulation.
         For simulation answer a suitable surrogate for the struct types"
        ^cTypeString caseOf:
           {    [#'unsigned long']                                                      ->      [value].
                [#'unsigned int']                                                       ->      [value].
+               [#'unsigned short']                                                     ->      [value].
+               [#sqInt]                                                                        ->      [value].
-               [#sqInt]                                                                                ->      [value].
                [#'sqIntptr_t']                                                         ->      [value].
                [#'usqIntptr_t']                                                                ->      [value].
                [#usqInt]                                                                       ->      [value].
                [#sqLong]                                                                       ->      [value].
+               [#usqLong]                                                              ->      [value].
-               [#usqLong]                                                                      ->      [value].
                [#'AbstractInstruction *']                                      ->      [value].
                [#'BytecodeFixup *']                                            ->      [value].
                [#'CogMethod *']                                                        ->      [value].
                [#'char *']                                                                     ->      [value].
                [#'sqInt *']                                                                    ->      [value].
                [#'void *']                                                                     ->      [value].
                [#void]                                                                         ->      [value].
                [#'void (*)()']                                                         ->      [value].
                [#'void (*)(void)']                                                     ->      [value].
                [#'unsigned long (*)(void)']                                    ->      [value].
                [#'void (*)(unsigned long,unsigned long)']      ->      [value].
                [#'usqIntptr_t (*)(void)']                                      ->      [value] }!

Item was changed:
  ----- Method: CogObjectRepresentationFor64BitSpur>>genPrimitiveAtPut (in category 'primitive generators') -----
(excessive size, no diff calculated)

Item was changed:
  ----- Method: FFIPlugin class>>moduleName (in category 'translation') -----
  moduleName "FFIPlugin translate"
        "IMPORTANT: IF YOU CHANGE THE NAME OF THIS PLUGIN YOU MUST CHANGE
                Interpreter>>primitiveCalloutToFFI
        TO REFLECT THE CHANGE."
+       ^'SqueakFFIPrims (Obsolete)'!
-       ^'SqueakFFIPrims'!

Item was changed:
  ----- Method: FilePluginSimulator>>sqFileDeleteName:Size: (in category 'simulation') -----
  sqFileDeleteName: nameIndex Size: nameSize
        | path |
+       path := interpreterProxy asString: nameIndex size: nameSize.
-       path := interpreterProxy interpreter asString: nameIndex size: nameSize.
        (StandardFileStream isAFileNamed: path) ifFalse:
                [^interpreterProxy primitiveFail].
        [FileDirectory deleteFilePath: path]
                on: Error
                do: [:ex| interpreterProxy primitiveFail]!

Item was changed:
  ----- Method: LargeIntegersPlugin>>cDigitSub:len:with:len:into: (in category 'C core') -----
  cDigitSub: pWordSmall
                len: smallLen
                with: pWordLarge
                len: largeLen
                into: pWordRes
        | z |
        <var: #pWordSmall type: #'unsigned int *'>
        <var: #pWordLarge type: #'unsigned int *'>
        <var: #pWordRes type: #'unsigned int *'>
        <var: #z type: #'unsigned long long'>

        z := 0.
        0 to: smallLen - 1 do:
                [:i |
                z := z + (self cDigitOf: pWordLarge at: i) - (self cDigitOf: pWordSmall at: i).
                self cDigitOf: pWordRes at: i put: (z bitAnd: 16rFFFFFFFF).
+               z := 0 - (self cCode: [z >> 63] inSmalltalk: [z >> 63 bitAnd: 1])].
-               z := 0 - (z >> 63)].
        smallLen to: largeLen - 1 do:
                [:i |
                z := z + (self cDigitOf: pWordLarge at: i) .
                self cDigitOf: pWordRes at: i put: (z bitAnd: 16rFFFFFFFF).
+               z := 0 - (self cCode: [z >> 63] inSmalltalk: [z >> 63 bitAnd: 1])].
-               z := 0 - (z >> 63)].
        ^0!

Item was changed:
  ----- Method: Spur64BitMMLECoSimulatorFor64Bits>>long64At: (in category 'memory access') -----
  long64At: byteAddress
+       "memory is a DoubleWordArray, a 64-bit indexable array of bits"
-       "memory is a DobleWordArray, a 64-bit indexable array of bits"
        byteAddress \\ 8 ~= 0 ifTrue: [self unalignedAccessError].
        ^memory at: byteAddress // 8 + 1!

Item was changed:
  ----- Method: Spur64BitMMLECoSimulatorFor64Bits>>long64At:put: (in category 'memory access') -----
  long64At: byteAddress put: a64BitValue
+       "memory is a DoubleWordArray, a 64-bit indexable array of bits"
-       "memory is a DobleWordArray, a 64-bit indexable array of bits"
        byteAddress \\ 8 ~= 0 ifTrue: [self unalignedAccessError].
        ^memory at: byteAddress // 8 + 1 put: a64BitValue!

Item was changed:
  ----- Method: Spur64BitMMLESimulatorFor64Bits>>long32At:put: (in category 'memory access') -----
  long32At: byteAddress put: a32BitValue
        "Store the 32-bit word at byteAddress which must be a multiple of four."
        | lowBits long longAddress |
+       a32BitValue < 0 ifTrue:
+               [self long32At: byteAddress put: (a32BitValue bitAnd: 16rFFFFFFFF).
+                ^a32BitValue].
        lowBits := byteAddress bitAnd: 4.
        lowBits = 0
                ifTrue: "storing into LS word"
                        [long := self long64At: byteAddress.
                         self long64At: byteAddress
                                put: ((long bitAnd: 16rFFFFFFFF00000000) bitOr: a32BitValue)]
                ifFalse: "storing into MS word"
                        [longAddress := byteAddress - 4.
                        long := self long64At: longAddress.
                        self long64At: longAddress
                                put: ((long bitAnd: 16rFFFFFFFF) bitOr: (a32BitValue bitShift: 32))].
        ^a32BitValue!

Item was changed:
  ----- Method: Spur64BitMMLESimulatorFor64Bits>>long64At:put: (in category 'memory access') -----
  long64At: byteAddress put: a64BitValue
+       "memory is a DoubleWordArray, a 64-bit indexable array of bits"
-       "memory is a DobleWordArray, a 64-bit indexable array of bits"
        byteAddress \\ 8 ~= 0 ifTrue: [self unalignedAccessError].
        ^memory at: byteAddress // 8 + 1 put: a64BitValue!

Item was added:
+ ----- Method: SpurMemoryManager>>ISA (in category 'simulation only') -----
+ ISA
+       "hack around the CoInterpreter/ObjectMemory split refactoring"
+       <doNotGenerate>
+       ^coInterpreter ISA!

Item was added:
+ ----- Method: SpurMemoryManager>>signed64BitIntegerFor: (in category 'simulation only') -----
+ signed64BitIntegerFor: integerValue
+       "hack around the CoInterpreter/ObjectMemory split refactoring"
+       <doNotGenerate>
+       ^coInterpreter signed64BitIntegerFor: integerValue!

Item was added:
+ ----- Method: SpurMemoryManager>>signed64BitValueOf: (in category 'simulation only') -----
+ signed64BitValueOf: oop
+       "hack around the CoInterpreter/ObjectMemory split refactoring"
+       <doNotGenerate>
+       ^coInterpreter signed64BitValueOf: oop!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedLong32At: (in category 'simulation') -----
+ unalignedLong32At: index
+       "Support for primitiveFFIIntegerAt[Put]"
+       <doNotGenerate>
+       | odd hi lo |
+       (odd := index bitAnd: 3) = 0 ifTrue:
+               [^self long32At: index].
+       lo := self long32At: index - odd.
+       hi := self long32At: index + 4 - odd.
+       ^lo >> (odd * 8) + ((hi bitAnd: 1 << (odd * 8) - 1) << (4 - odd * 8))!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedLong32At:put: (in category 'simulation') -----
+ unalignedLong32At: index put: aValue
+       "Support for primitiveFFIIntegerAt[Put]"
+       <doNotGenerate>
+       | odd hi lo mask |
+       aValue < 0 ifTrue:
+               [self unalignedLong64At: index put: (aValue bitAnd: 16rFFFFFFFF).
+                ^aValue].
+       (odd := index bitAnd: 3) = 0 ifTrue:
+               [^self long32At: index put: aValue].
+       mask := 1 << (odd * 8) - 1.
+       lo := self long32At: index - odd.
+       self long32At: index - odd
+               put: (lo bitAnd: mask)
+                       + ((aValue bitAnd: 1 << (4 - odd * 8) - 1) << (odd * 8)).
+       hi := self long32At: index + 4 - odd.
+       self long32At: index + 4 - odd
+               put: (hi bitClear: mask) + (aValue >> (4 - odd * 8) bitAnd: mask).
+       ^aValue!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedLong64At: (in category 'simulation') -----
+ unalignedLong64At: index
+       "Support for primitiveFFIIntegerAt[Put]"
+       <doNotGenerate>
+       | odd hi lo |
+       (odd := index bitAnd: 7) = 0 ifTrue:
+               [^self long64At: index].
+       lo := self long64At: index - odd.
+       hi := self long64At: index + 8 - odd.
+       ^lo >> (odd * 8) + ((hi bitAnd: 1 << (odd * 8) - 1) << (8 - odd * 8))!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedLong64At:put: (in category 'simulation') -----
+ unalignedLong64At: index put: aValue
+       "Support for primitiveFFIIntegerAt[Put]"
+       <doNotGenerate>
+       | odd hi lo mask |
+       aValue < 0 ifTrue:
+               [self unalignedLong64At: index put: (aValue bitAnd: 16rFFFFFFFFFFFFFFFF).
+                ^aValue].
+       (odd := index bitAnd: 7) = 0 ifTrue:
+               [^self long64At: index put: aValue].
+       mask := 1 << (odd * 8) - 1.
+       lo := self long64At: index - odd.
+       self long64At: index - odd
+               put: (lo bitAnd: mask)
+                       + ((aValue bitAnd: 1 << (8 - odd * 8) - 1) << (odd * 8)).
+       hi := self long64At: index + 8 - odd.
+       self long64At: index + 8 - odd
+               put: (hi bitClear: mask) + (aValue >> (8 - odd * 8) bitAnd: mask).
+       ^aValue!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedShortAt: (in category 'simulation') -----
+ unalignedShortAt: index
+       "Support for primitiveFFIIntegerAt[Put]"
+       <doNotGenerate>
+       | hi lo |
+       (index bitAnd: 1) = 0 ifTrue:
+               [^self shortAt: index].
+       lo := self shortAt: index - 1.
+       hi := self shortAt: index + 1.
+       ^lo >> 8 + ((hi bitAnd: 16rFF) << 8)!

Item was added:
+ ----- Method: SpurMemoryManager>>unalignedShortAt:put: (in category 'simulation') -----
+ unalignedShortAt: index put: aValue
+       "Support for primitiveFFIIntegerAt[Put]"
+       <doNotGenerate>
+       (index bitAnd: 1) = 0 ifTrue:
+               [^self shortAt: index put: aValue].
+       self shouldBeImplemented.
+       ^aValue!

Item was added:
+ ----- Method: StackInterpreter>>ISA (in category 'simulation') -----
+ ISA
+       <doNotGenerate>
+       ^self class initializationOptions
+               at: #ISA
+               ifAbsent: [Smalltalk wordSize = 8
+                                       ifTrue: [#X64]
+                                       ifFalse: [#IA32]]!

Item was changed:
  ----- Method: StackInterpreter>>ioLoadExternalFunction:OfLength:FromModule:OfLength:AccessorDepthInto: (in category 'primitive support') -----
  ioLoadExternalFunction: functionName OfLength: functionLength FromModule: moduleName OfLength: moduleLength AccessorDepthInto: accessorDepthPtr
        "Load and return the requested function from a module.  Assign the accessor depth through accessorDepthPtr.
         N.B. The actual code lives in platforms/Cross/vm/sqNamedPrims.h"
        <doNotGenerate>
        | pluginString functionString |
        pluginString := String new: moduleLength.
+       (1 to: moduleLength) do:[:i| pluginString byteAt: i put: (objectMemory byteAt: moduleName+i-1)].
-       1 to: moduleLength do:[:i| pluginString byteAt: i put: (objectMemory byteAt: moduleName+i-1)].
        functionString := String new: functionLength.
+       (1 to: functionLength) do:[:i| functionString byteAt: i put: (objectMemory byteAt: functionName+i-1)].
+       "We used to ignore loads of the SqueakFFIPrims plugin, but that means doing without integerAt:[put:]size:signed:
+        which is too much of a limitation (not that these simulate unaligned accesses yet)."
-       1 to: functionLength do:[:i| functionString byteAt: i put: (objectMemory byteAt: functionName+i-1)].
-       "Pharo images as of 2016 use the FFI plugin (for getenv:?).  We can't simulate such function loads.  So ignore"
-       pluginString = 'SqueakFFIPrims' ifTrue:
-               ["self halt."
-                true ifTrue:
-                       [self transcript cr; show: 'ignoring function load from SqueakFFIPrims'.
-                        ^0]].
        ^self ioLoadFunction: functionString From: pluginString AccessorDepthInto: accessorDepthPtr!

Item was changed:
  ----- Method: ThreadedFFIPlugin class>>preambleCCode (in category 'translation') -----
  preambleCCode
        "For a source of builtin defines grep for builtin_define in a gcc release config directory."
        ^'
  #include "sqAssert.h" /* for assert */
  #define ThreadedFFIPlugin 1 /* to filter-out unwanted declarations from sqFFI.h */
  #include "sqFFI.h" /* for logging and surface functions */
  #include "sqCogStackAlignment.h" /* for STACK_ALIGN_BYTES and getsp() */

  #ifdef _MSC_VER
  # define alloca _alloca
  #endif
  #if defined(__GNUC__) && (defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__))
  # define setsp(sp) asm volatile ("movl %0,%%esp" : : "m"(sp))
  # elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__) ||  defined(__amd64) || defined(__x86_64))
  # define setsp(sp) asm volatile ("movq %0,%%rsp" : : "m"(sp))
  # elif defined(__GNUC__) && (defined(__arm__))
  # define setsp(sp) asm volatile ("ldr %%sp, %0" : : "m"(sp))
  #endif
  #if !!defined(getsp)
  # define getsp() 0
  #endif
  #if !!defined(setsp)
  # define setsp(ignored) 0
  #endif

  #if !!defined(STACK_ALIGN_BYTES)
  #  define STACK_ALIGN_BYTES 0
  #endif /* !!defined(STACK_ALIGN_BYTES) */

  /* For ABI that require stack alignment greater than natural word size */
  #define MUST_ALIGN_STACK (STACK_ALIGN_BYTES > sizeof(void*))

  #if defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__)
  /* Both Mac OS X x86 and Win32 x86 return structs of a power of two in size
   * less than or equal to eight bytes in length in registers. Linux never does so.
   */
  # if __linux__
  #     define WIN32_X86_STRUCT_RETURN 0
  # else
  #     define WIN32_X86_STRUCT_RETURN 1
  # endif
  # if _WIN32
  #     define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 1
  # endif
  # elif defined(__amd64__) || defined(__x86_64__) ||  defined(__amd64) || defined(__x86_64)
  # if _WIN32 | _WIN64
  #     define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 1
  # endif
  #endif /* defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__) */

  #if !!defined(ALLOCA_LIES_SO_SETSP_BEFORE_CALL)
  # if defined(__MINGW32__) && !!defined(__clang__) && (__GNUC__ >= 3) && (defined(_X86_) || defined(i386) || defined(__i386) || defined(__i386__))
      /*
       * cygwin -mno-cygwin (MinGW) gcc 3.4.x''s alloca is a library routine that answers
       * %esp + xx, so the outgoing stack is offset by one or more word if uncorrected.
       * Grab the actual stack pointer to correct.
       */
  #     define ALLOCA_LIES_SO_SETSP_BEFORE_CALL 1
  # else
  #     define ALLOCA_LIES_SO_SETSP_BEFORE_CALL 0
  # endif
  #endif /* !!defined(ALLOCA_LIES_SO_SETSP_BEFORE_CALL) */

  #if !!defined(PLATFORM_API_USES_CALLEE_POPS_CONVENTION)
  # define PLATFORM_API_USES_CALLEE_POPS_CONVENTION 0
  #endif

+ /* This alignment stuff is a hack for integerAt:put:size:signed:/primitiveFFIIntegerAt[Put].
+  * The assumption right now is that all processors suppoprt unaligned access.  That only
+  * holds true for x86, x86-64 & ARMv6 & later.  But this keeps us going until we can addresws it properly.
+  */
+ #define unalignedShortAt(a) shortAt(a)
+ #define unalignedShortAtput(a) shortAtput(a)
+ #define unalignedLong32At(a) long32At(a)
+ #define unalignedLong32Atput(a) long32Atput(a)
+ #define unalignedLong64At(a) long64At(a)
+ #define unalignedLong64Atput(a) long64Atput(a)
+
  /* The dispatchOn:in:with:with: generates an unwanted call on error.  Just squash it. */
  #define error(foo) 0
  #ifndef SQUEAK_BUILTIN_PLUGIN
  /* but print assert failures. */
  void
  warning(char *s) { /* Print an error message but don''t exit. */
        printf("\n%s\n", s);
  }
  #endif

  /* sanitize */
  #ifdef SQUEAK_BUILTIN_PLUGIN
  # define EXTERN
  #else
  # define EXTERN extern
  #endif
  '!

Item was added:
+ ----- Method: ThreadedFFIPlugin>>initSurfacePluginFunctionPointers (in category 'simulation') -----
+ initSurfacePluginFunctionPointers
+       "This is a simulation-only stub.  The real code is in
+               platforms/Cross/plugins/SqueakFFIPrims/sqManualSurface.c"
+       <doNotGenerate>!

Item was changed:
  ----- Method: ThreadedFFIPlugin>>initialiseModule (in category 'initialize') -----
  initialiseModule
        <export: true>
        "By default, disable logging"
        ffiLogEnabled := false.
        "Get the instSize of ExternalFunction to know whether it contains a cache of the stackSize,
         and what the offset of ExternalLibraryFunction's functionName and moduleName slots are."
        externalFunctionInstSize := interpreterProxy instanceSizeOf: interpreterProxy classExternalFunction.
        self initSurfacePluginFunctionPointers.
+       ^true!
-       ^1!

Item was added:
+ ----- Method: ThreadedFFIPlugin>>morphIntoConcreteSubclass: (in category 'simulation') -----
+ morphIntoConcreteSubclass: aCoInterpreter
+       <doNotGenerate>
+       | concreteClass |
+       concreteClass :=
+               aCoInterpreter ISA caseOf: {
+                       [#X64]          ->      [(Smalltalk platformName beginsWith: 'Win')
+                                                               ifTrue: [ThreadedX64Win64FFIPlugin]
+                                                               ifFalse: [ThreadedX64SysVFFIPlugin]].
+                       [#IA32] ->      [ThreadedIA32FFIPlugin].
+                       [#ARMv5]        ->      [ThreadedARMFFIPlugin] }
+                       otherwise: [self error: 'simulation not set up for this ISA'].
+       self changeClassTo: concreteClass!

Item was changed:
  ----- Method: ThreadedFFIPlugin>>primitiveFFIIntegerAt (in category 'primitives') -----
  primitiveFFIIntegerAt
        "Answer a (signed or unsigned) n byte integer from the given byte offset
         in the receiver, using the platform's endianness."
        | isSigned byteSize byteOffset rcvr addr value mask valueOop |
        <var: 'value' type: #usqLong>
        <var: 'mask' type: #usqLong>
        <export: true>
        <inline: false>
        isSigned := interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0).
        byteSize := interpreterProxy stackIntegerValue: 1.
        byteOffset := interpreterProxy stackIntegerValue: 2.
        rcvr := interpreterProxy stackObjectValue: 3.
        interpreterProxy failed ifTrue:[^0].
        (byteOffset > 0
         and: [(byteSize between: 1 and: 8)
         and: [(byteSize bitAnd: byteSize - 1) = 0 "a.k.a. isPowerOfTwo"]]) ifFalse:
                [^interpreterProxy primitiveFail].
        addr := self ffiAddressOf: rcvr startingAt: byteOffset size: byteSize.
        interpreterProxy failed ifTrue:[^0].
        byteSize <= 2
                ifTrue:
                        [byteSize = 1
                                ifTrue: [value := self cCoerceSimple: (interpreterProxy byteAt: addr) to: #'unsigned char']
+                               ifFalse: [value := self cCoerceSimple: (interpreterProxy unalignedShortAt: addr) to: #'unsigned short']]
-                               ifFalse: [value := self cCoerceSimple: (interpreterProxy shortAt: addr) to: #'unsigned short']]
                ifFalse:
                        [byteSize = 4
+                               ifTrue: [value := self cCoerceSimple: (interpreterProxy unalignedLong32At: addr) to: #'unsigned int']
+                               ifFalse: [value := interpreterProxy unalignedLong64At: addr]].
-                               ifTrue: [value := self cCoerceSimple: (interpreterProxy long32At: addr) to: #'unsigned int']
-                               ifFalse: [value := interpreterProxy long64At: addr]].
        byteSize < BytesPerWord
                ifTrue:
                        [isSigned ifTrue: "sign extend value"
                                [mask := 1 asUnsignedLongLong << (byteSize * 8 - 1).
                                value := (value bitAnd: mask-1) - (value bitAnd: mask)].
                         "note: byte/short (&long if BytesPerWord=8) never exceed SmallInteger range"
                         valueOop := interpreterProxy integerObjectOf: value]
                ifFalse: "general 64 bit integer; note these never fail"
                        [isSigned
                                ifTrue:
                                        [byteSize < 8 ifTrue: "sign extend value"
                                                [mask := 1 asUnsignedLongLong << (byteSize * 8 - 1).
                                                value := (value bitAnd: mask-1) - (value bitAnd: mask)].
+                                        self cCode: [] inSmalltalk:
+                                               [(byteSize = 8 and: [(value bitShift: -56) >= 128]) ifTrue:
+                                                       [value := value - (1 bitShift: 64)]].
                                         valueOop := interpreterProxy signed64BitIntegerFor: value]
                                ifFalse:[valueOop := interpreterProxy positive64BitIntegerFor: value]].
        ^interpreterProxy pop: 4 thenPush: valueOop!

Item was changed:
  ----- Method: ThreadedFFIPlugin>>primitiveFFIIntegerAtPut (in category 'primitives') -----
  primitiveFFIIntegerAtPut
        "Store a (signed or unsigned) n byte integer at the given byte offset
         in the receiver, using the platform's endianness."
        | isSigned byteSize byteOffset rcvr addr value max valueOop |
        <var: 'value' type: #sqLong>
        <var: 'max' type: #sqLong>
        <export: true>
        <inline: false>
        isSigned := interpreterProxy booleanValueOf: (interpreterProxy stackValue: 0).
        byteSize := interpreterProxy stackIntegerValue: 1.
        valueOop := interpreterProxy stackValue: 2.
        byteOffset := interpreterProxy stackIntegerValue: 3.
        rcvr := interpreterProxy stackObjectValue: 4.
        interpreterProxy failed ifTrue:[^0].
        (byteOffset > 0
         and: [(byteSize between: 1 and: 8)
         and: [(byteSize bitAnd: byteSize - 1) = 0 "a.k.a. isPowerOfTwo"]]) ifFalse:
                [^interpreterProxy primitiveFail].
        addr := self ffiAddressOf: rcvr startingAt: byteOffset size: byteSize.
        interpreterProxy failed ifTrue:[^0].
        isSigned
                ifTrue:[value := interpreterProxy signed64BitValueOf: valueOop]
                ifFalse:[value := interpreterProxy positive64BitValueOf: valueOop].
        interpreterProxy failed ifTrue:[^0].
        byteSize < 8 ifTrue:
                [isSigned
                        ifTrue:
                                [max := 1 asUnsignedLongLong << (8 * byteSize - 1).
                                (value >= (0 - max) and: [value < max]) ifFalse: [^interpreterProxy primitiveFail]]
                        ifFalse:
                                [value asUnsignedLongLong < (1 asUnsignedLongLong << (8 * byteSize)) ifFalse: [^interpreterProxy primitiveFail]]].
        byteSize <= 2
                ifTrue:
                        [byteSize = 1
                                ifTrue: [interpreterProxy byteAt: addr put: value]
+                               ifFalse: [interpreterProxy unalignedShortAt: addr put: value]]
-                               ifFalse: [interpreterProxy shortAt: addr put: value]]
                ifFalse:
                        [byteSize = 4
+                               ifTrue: [interpreterProxy unalignedLong32At: addr put: value]
+                               ifFalse: [interpreterProxy unalignedLong64At: addr put: value]].
-                               ifTrue: [interpreterProxy long32At: addr put: value]
-                               ifFalse: [interpreterProxy long64At: addr put: value]].
        ^interpreterProxy pop: 5 thenPush: valueOop!

Item was added:
+ ----- Method: ThreadedFFIPlugin>>setInterpreter: (in category 'simulation') -----
+ setInterpreter: anInterpreter
+       "Initialization of the plugin in the simulator.
+        The real routine is in the superclass."
+       self cCode: []
+               inSmalltalk: [self class == thisContext method methodClass ifTrue:
+                                               [self morphIntoConcreteSubclass: anInterpreter]].
+       ^super setInterpreter: anInterpreter!