-!IF DEFINED(DEBUG)
-LINK_FLAGS = /nologo /safeseh /DEBUG shell32.lib
-CL_FLAGS = /nologo /Zi /O2 /W3 /DFACTOR_DEBUG
-!ELSE
-LINK_FLAGS = /nologo /safeseh shell32.lib
+!IF DEFINED(PLATFORM)
+
+LINK_FLAGS = /nologo shell32.lib
CL_FLAGS = /nologo /O2 /W3
+
+!IF DEFINED(DEBUG)
+LINK_FLAGS = $(LINK_FLAGS) /DEBUG
+CL_FLAGS = $(CL_FLAGS) /Zi /DFACTOR_DEBUG
+!ENDIF
+
+!IF "$(PLATFORM)" == "x86-32"
+LINK_FLAGS = $(LINK_FLAGS) /safeseh
+PLAF_DLL_OBJS = vm\os-windows-nt-x86.32.obj vm\safeseh.obj
+!ELSEIF "$(PLATFORM)" == "x86-64"
+PLAF_DLL_OBJS = vm\os-windows-nt-x86.64.obj
!ENDIF
ML_FLAGS = /nologo /safeseh
EXE_OBJS = vm\main-windows-nt.obj vm\factor.res
-DLL_OBJS = vm\os-windows-nt.obj \
+DLL_OBJS = $(PLAF_DLL_OBJS) \
vm\os-windows.obj \
+ vm\os-windows-nt.obj \
vm\aging_collector.obj \
vm\alien.obj \
vm\arrays.obj \
vm\profiler.obj \
vm\quotations.obj \
vm\run.obj \
- vm\safeseh.obj \
vm\strings.obj \
vm\to_tenured_collector.obj \
vm\tuples.obj \
.rs.res:
rc $<
-all: factor.com factor.exe factor.dll.lib libfactor-ffi-test.dll
-
libfactor-ffi-test.dll: vm/ffi_test.obj
link $(LINK_FLAGS) /out:libfactor-ffi-test.dll /dll vm/ffi_test.obj
factor.exe: $(EXE_OBJS) $(DLL_OBJS)
link $(LINK_FLAGS) /out:factor.exe /SUBSYSTEM:windows $(EXE_OBJS) $(DLL_OBJS)
+all: factor.com factor.exe factor.dll.lib libfactor-ffi-test.dll
+
+!ENDIF
+
+default:
+ @echo Usage: nmake /f Nmakefile platform
+ @echo Where platform is one of:
+ @echo x86-32
+ @echo x86-64
+ @exit 1
+
+x86-32:
+ nmake PLATFORM=x86-32 /f Nmakefile all
+
+x86-64:
+ nmake PLATFORM=x86-64 /f Nmakefile all
+
clean:
del vm\*.obj
del factor.lib
del factor.dll
del factor.dll.lib
-.PHONY: all clean
+.PHONY: all default x86-32 x86-64 clean
.SUFFIXES: .rs
[ align-code ]
bi ;
-M: x86.32 pic-tail-reg EBX ;
+M: x86.32 pic-tail-reg EDX ;
M: x86.32 reserved-stack-space 0 ;
: div-arg ( -- reg ) EAX ;
: mod-arg ( -- reg ) EDX ;
: temp0 ( -- reg ) EAX ;
-: temp1 ( -- reg ) EDX ;
-: temp2 ( -- reg ) ECX ;
-: temp3 ( -- reg ) EBX ;
+: temp1 ( -- reg ) ECX ;
+: temp2 ( -- reg ) EBX ;
+: temp3 ( -- reg ) EDX ;
+: pic-tail-reg ( -- reg ) EDX ;
: stack-reg ( -- reg ) ESP ;
: frame-reg ( -- reg ) EBP ;
-: vm-reg ( -- reg ) ECX ;
+: vm-reg ( -- reg ) EBX ;
: ctx-reg ( -- reg ) EBP ;
: nv-regs ( -- seq ) { ESI EDI EBX } ;
-: nv-reg ( -- reg ) EBX ;
+: nv-reg ( -- reg ) ESI ;
: ds-reg ( -- reg ) ESI ;
: rs-reg ( -- reg ) EDI ;
: fixnum>slot@ ( -- ) temp0 2 SAR ;
] jit-prolog jit-define
[
- temp3 0 MOV rc-absolute-cell rt-here jit-rel
+ pic-tail-reg 0 MOV rc-absolute-cell rt-here jit-rel
0 JMP rc-relative rt-entry-point-pic-tail jit-rel
] jit-word-jump jit-define
: jit-save-context ( -- )
jit-load-context
- EDX ESP -4 [+] LEA
- ctx-reg context-callstack-top-offset [+] EDX MOV
+ ECX ESP -4 [+] LEA
+ ctx-reg context-callstack-top-offset [+] ECX MOV
ctx-reg context-datastack-offset [+] ds-reg MOV
ctx-reg context-retainstack-offset [+] rs-reg MOV ;
[
! Load callstack object
- EBX ds-reg [] MOV
+ temp3 ds-reg [] MOV
ds-reg bootstrap-cell SUB
! Get ctx->callstack_bottom
jit-load-vm
jit-load-context
- EAX ctx-reg context-callstack-bottom-offset [+] MOV
+ temp0 ctx-reg context-callstack-bottom-offset [+] MOV
! Get top of callstack object -- 'src' for memcpy
- EBP EBX callstack-top-offset [+] LEA
+ temp1 temp3 callstack-top-offset [+] LEA
! Get callstack length, in bytes --- 'len' for memcpy
- EDX EBX callstack-length-offset [+] MOV
- EDX tag-bits get SHR
+ temp2 temp3 callstack-length-offset [+] MOV
+ temp2 tag-bits get SHR
! Compute new stack pointer -- 'dst' for memcpy
- EAX EDX SUB
+ temp0 temp2 SUB
! Install new stack pointer
- ESP EAX MOV
+ ESP temp0 MOV
! Call memcpy
- EDX PUSH
- EBP PUSH
- EAX PUSH
+ temp2 PUSH
+ temp1 PUSH
+ temp0 PUSH
"factor_memcpy" jit-call
ESP 12 ADD
! Return with new callstack
! Inline cache miss entry points
: jit-load-return-address ( -- )
- EBX ESP stack-frame-size bootstrap-cell - [+] MOV ;
+ pic-tail-reg ESP stack-frame-size bootstrap-cell - [+] MOV ;
! These are always in tail position with an existing stack
! frame, and the stack. The frame setup takes this into account.
jit-load-vm
jit-save-context
ESP 4 [+] vm-reg MOV
- ESP [] EBX MOV
+ ESP [] pic-tail-reg MOV
"inline_cache_miss" jit-call
jit-restore-context ;
[
ESP [] EAX MOV
ESP 4 [+] EDX MOV
+ jit-load-vm
ESP 8 [+] vm-reg MOV
jit-call
]
EBX tag-bits get SAR
ESP [] EBX MOV
ESP 4 [+] EBP MOV
+ jit-load-vm
ESP 8 [+] vm-reg MOV
"overflow_fixnum_multiply" jit-call
]
! Load context and parameter from datastack
EAX ds-reg [] MOV
EAX EAX alien-offset [+] MOV
- EBX ds-reg -4 [+] MOV
+ EDX ds-reg -4 [+] MOV
ds-reg 8 SUB
! Make the new context active
! Store parameter to datastack
ds-reg 4 ADD
- ds-reg [] EBX MOV ;
+ ds-reg [] EDX MOV ;
[ jit-set-context ] \ (set-context) define-sub-primitive
"new_context" jit-call
! Save pointer to quotation and parameter
- EBX ds-reg MOV
+ EDX ds-reg MOV
ds-reg 8 SUB
! Make the new context active
EAX jit-switch-context
! Push parameter
- EAX EBX -4 [+] MOV
+ EAX EDX -4 [+] MOV
ds-reg 4 ADD
ds-reg [] EAX MOV
0 PUSH
! Jump to initial quotation
- EAX EBX [] MOV
+ EAX EDX [] MOV
jit-jump-quot ;
[ jit-start-context ] \ (start-context) define-sub-primitive
: shift-arg ( -- reg ) RCX ;
: div-arg ( -- reg ) RAX ;
: mod-arg ( -- reg ) RDX ;
-: temp0 ( -- reg ) RDI ;
-: temp1 ( -- reg ) RSI ;
+: temp0 ( -- reg ) RAX ;
+: temp1 ( -- reg ) RCX ;
: temp2 ( -- reg ) RDX ;
: temp3 ( -- reg ) RBX ;
+: pic-tail-reg ( -- reg ) RBX ;
: return-reg ( -- reg ) RAX ;
: nv-reg ( -- reg ) RBX ;
: stack-reg ( -- reg ) RSP ;
] jit-prolog jit-define
[
- temp3 5 [RIP+] LEA
+ pic-tail-reg 5 [RIP+] LEA
0 JMP rc-relative rt-entry-point-pic-tail jit-rel
] jit-word-jump jit-define
[
! Optimizing compiler's side of callback accesses
! arguments that are on the stack via the frame pointer.
- ! On x86-64, some arguments are passed in registers, and
- ! so the only register that is safe for use here is nv-reg.
+ ! On x86-32 fastcall, and x86-64, some arguments are passed
+ ! in registers, and so the only registers that are safe for
+ ! use here are frame-reg, nv-reg and vm-reg.
frame-reg PUSH
frame-reg stack-reg MOV
[
! Load word
- nv-reg 0 MOV rc-absolute-cell rt-literal jit-rel
+ temp0 0 MOV rc-absolute-cell rt-literal jit-rel
! Bump profiling counter
- nv-reg profile-count-offset [+] 1 tag-fixnum ADD
+ temp0 profile-count-offset [+] 1 tag-fixnum ADD
! Load word->code
- nv-reg nv-reg word-code-offset [+] MOV
+ temp0 temp0 word-code-offset [+] MOV
! Compute word entry point
- nv-reg compiled-header-size ADD
+ temp0 compiled-header-size ADD
! Jump to entry point
- nv-reg JMP
+ temp0 JMP
] jit-profiling jit-define
[
! ! ! Polymorphic inline caches
-! The PIC stubs are not permitted to touch temp3.
+! The PIC stubs are not permitted to touch pic-tail-reg.
! Load a value from a stack position
[
! load value
temp3 ds-reg [] MOV
! make a copy
- temp1 temp3 MOV
- ! compute positive shift value in temp1
- temp1 CL SHL
+ temp2 temp3 MOV
+ ! compute positive shift value in temp2
+ temp2 CL SHL
shift-arg NEG
! compute negative shift value in temp3
temp3 CL SAR
temp3 tag-mask get bitnot AND
shift-arg 0 CMP
- ! if shift count was negative, move temp0 to temp1
- temp1 temp3 CMOVGE
+ ! if shift count was negative, move temp0 to temp2
+ temp2 temp3 CMOVGE
! push to stack
- ds-reg [] temp1 MOV
+ ds-reg [] temp2 MOV
] \ fixnum-shift-fast define-sub-primitive
: jit-fixnum-/mod ( -- )
! load second parameter
- temp3 ds-reg [] MOV
+ temp1 ds-reg [] MOV
! load first parameter
div-arg ds-reg bootstrap-cell neg [+] MOV
! make a copy
! sign-extend
mod-arg bootstrap-cell-bits 1 - SAR
! divide
- temp3 IDIV ;
+ temp1 IDIV ;
[
jit-fixnum-/mod
M: no-word-error summary
name>>
- "No word named ``"
- "'' found in current vocabulary search path" surround ;
+ "No word named “"
+ "” found in current vocabulary search path" surround ;
M: no-word-error error. summary print ;
M: no-word-in-vocab summary
[ vocab>> ] [ word>> ] bi
- [ "No word named ``" % % "'' found in ``" % % "'' vocabulary" % ] "" make ;
+ [ "No word named “" % % "” found in “" % % "” vocabulary" % ] "" make ;
M: no-word-in-vocab error. summary print ;
M: ambiguous-use-error summary
words>> first name>>
- "More than one vocabulary defines a word named ``" "''" surround ;
+ "More than one vocabulary defines a word named “" "”" surround ;
M: ambiguous-use-error error. summary print ;
M: not-in-a-method-error summary
drop "call-next-method can only be called in a method definition" ;
+M: version-control-merge-conflict summary
+ drop "Version control merge conflict in source code" ;
+
GENERIC: expected>string ( obj -- str )
M: f expected>string drop "end of input" ;
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors sequences assocs arrays continuations
destructors combinators kernel threads concurrency.messaging
concurrency.mailboxes concurrency.promises io.files io.files.info
-io.directories io.pathnames io.monitors debugger fry ;
+io.directories io.pathnames io.monitors io.monitors.private
+debugger fry ;
IN: io.monitors.recursive
! Simulate recursive monitors on platforms that don't have them
] with with each ;
: pump-loop ( -- )
- receive dup +stop+ eq? [
- drop stop-pump
- ] [
- [ '[ _ update-hierarchy ] ignore-errors ] [ pump-step ] bi
- pump-loop
- ] if ;
+ receive {
+ { [ dup +stop+ eq? ] [ drop stop-pump ] }
+ { [ dup monitor-disposed eq? ] [ drop ] }
+ [
+ [ '[ _ update-hierarchy ] ignore-errors ] [ pump-step ] bi
+ pump-loop
+ ]
+ } cond ;
: monitor-ready ( error/t -- )
monitor tget ready>> fulfill ;
IN: ui.gadgets.grids
ARTICLE: "ui-grid-layout" "Grid layouts"
-"Grid gadgets layout their children in a rectangular grid."
+"Grid gadgets layout their children in a rectangular grid. The grid is represented as a sequence of sequences of gadgets. Every child sequence is a row of gadgets. Every row must have an equal number of gadgets in it."
{ $subsections grid }
"Creating grids from a fixed set of gadgets:"
{ $subsections <grid> }
"read-only"
"call("
"execute("
+ "<<<<<<"
+ "======"
+ ">>>>>>"
+ "<<<<<<<"
+ "======="
+ ">>>>>>>"
} [ "syntax" create drop ] each
"t" "syntax" lookup define-symbol
[ 7 ] [ 1 3 [ 2 * ] [ + ] compose compile-call(-test-1 ] unit-test
[ 4 ] [ 1 3 [ { + } [ ] like call ] compile-call(-test-1 ] unit-test
+[ [ ] call( -- * ) ] must-fail
+
+: compile-call(-test-2 ( -- ) [ ] call( -- * ) ;
+
+[ compile-call(-test-2 ] [ wrong-values? ] must-fail-with
+
+: compile-call(-test-3 ( quot -- ) call( -- * ) ;
+
+[ [ ] compile-call(-test-3 ] [ wrong-values? ] must-fail-with
+
+: compile-execute(-test-3 ( a -- ) \ . execute( value -- * ) ;
+
+[ 10 compile-execute(-test-3 ] [ wrong-values? ] must-fail-with
+
+: compile-execute(-test-4 ( a word -- ) execute( value -- * ) ;
+
+[ 10 \ . compile-execute(-test-4 ] [ wrong-values? ] must-fail-with
+
! Compiled
: cond-test-1 ( obj -- str )
{
! We can't USE: effects here so we forward reference slots instead
SLOT: in
SLOT: out
+SLOT: terminated?
: call-effect ( quot effect -- )
! Don't use fancy combinators here, since this word always
! runs unoptimized
- [ datastack ] 2dip
2dup [
- [ dip ] dip
- dup in>> length swap out>> length
- check-datastack
+ [ [ datastack ] dip dip ] dip
+ dup terminated?>> [ 2drop f ] [
+ dup in>> length swap out>> length
+ check-datastack
+ ] if
] 2dip rot
[ 2drop ] [ wrong-values ] if ;
: ?run-file ( path -- )
dup exists? [ run-file ] [ drop ] if ;
+
+ERROR: version-control-merge-conflict ;
"call(" [ \ call-effect parse-call( ] define-core-syntax
"execute(" [ \ execute-effect parse-call( ] define-core-syntax
+
+ "<<<<<<<" [ version-control-merge-conflict ] define-core-syntax
+ "=======" [ version-control-merge-conflict ] define-core-syntax
+ ">>>>>>>" [ version-control-merge-conflict ] define-core-syntax
+
+ "<<<<<<" [ version-control-merge-conflict ] define-core-syntax
+ "======" [ version-control-merge-conflict ] define-core-syntax
+ ">>>>>>" [ version-control-merge-conflict ] define-core-syntax
] with-compilation-unit
[ B{ } ] [ [ { } [ , ] each ] B{ } make ] unit-test
[ { 2 4 6 8 10 } ] [ { 1 2 3 4 5 } [ 2 * ] map ] unit-test
-[ { "roses: lutefisk" "tulips: lox" } ]
-[
- [
- { { "roses" "lutefisk" } { "tulips" "lox" } }
- [ ": " glue , ] assoc-each
- ] { } make
-] unit-test
-
-[ { "roses: lutefisk" "tulips: lox" } ]
-[
- { { "roses" "lutefisk" } { "tulips" "lox" } }
- [ ": " glue ] { } assoc>map
-] unit-test
-
[ { "roses: lutefisk" "tulips: lox" } ]
[
[
[ { 2 4 6 8 10 } ] [ { 1 2 3 4 5 } compile-test-map ] unit-test
[ { "roses: lutefisk" "tulips: lox" } ]
-[ [ { { "roses" "lutefisk" } { "tulips" "lox" } } compile-test-assoc-each ] { } make ] unit-test
+[
+ [ H{ { "roses" "lutefisk" } { "tulips" "lox" } } compile-test-assoc-each ]
+ { } make natural-sort
+] unit-test
[ { "roses: lutefisk" "tulips: lox" } ]
-[ { { "roses" "lutefisk" } { "tulips" "lox" } } compile-test-assoc>map ] unit-test
+[
+ H{ { "roses" "lutefisk" } { "tulips" "lox" } } compile-test-assoc>map
+ natural-sort
+] unit-test
MIXIN: input-cursor
-GENERIC: cursor-value ( cursor -- value )
+GENERIC: cursor-key-value ( cursor -- key value )
<PRIVATE
-GENERIC: cursor-value-unsafe ( cursor -- value )
+GENERIC: cursor-key-value-unsafe ( cursor -- key value )
PRIVATE>
-M: input-cursor cursor-value-unsafe cursor-value ; inline
-M: input-cursor cursor-value
- dup cursor-valid? [ cursor-value-unsafe ] [ invalid-cursor ] if ; inline
+M: input-cursor cursor-key-value-unsafe cursor-key-value ; inline
+M: input-cursor cursor-key-value
+ dup cursor-valid? [ cursor-key-value-unsafe ] [ invalid-cursor ] if ; inline
+
+: cursor-key ( cursor -- key ) cursor-key-value drop ;
+: cursor-value ( cursor -- key ) cursor-key-value nip ;
+
+: cursor-key-unsafe ( cursor -- key ) cursor-key-value-unsafe drop ;
+: cursor-value-unsafe ( cursor -- key ) cursor-key-value-unsafe nip ;
!
! output cursors
INSTANCE: numeric-cursor input-cursor
-M: numeric-cursor cursor-value value>> ; inline
+M: numeric-cursor cursor-key-value value>> dup ; inline
!
! linear cursor
INSTANCE: sequence-cursor input-cursor
-M: sequence-cursor cursor-value-unsafe [ n>> ] [ seq>> ] bi nth-unsafe ; inline
-M: sequence-cursor cursor-value [ n>> ] [ seq>> ] bi nth ; inline
+M: sequence-cursor cursor-key-value-unsafe [ n>> dup ] [ seq>> ] bi nth-unsafe ; inline
+M: sequence-cursor cursor-key-value [ n>> dup ] [ seq>> ] bi nth ; inline
INSTANCE: sequence-cursor output-cursor
over map-as ; inline
!
-! assoc cursors
+! assoc combinators
!
-MIXIN: assoc-cursor
-
-GENERIC: cursor-key-value ( cursor -- key value )
-
: -assoc- ( quot -- quot' )
'[ cursor-key-value @ ] ; inline
: assoc>map ( ... assoc quot: ( ... k v -- ... newx ) exemplar -- ... newcontainer )
[ assoc- ] dip -map-as ; inline
-INSTANCE: input-cursor assoc-cursor
-
-M: input-cursor cursor-key-value
- cursor-value-unsafe first2 ; inline
-
!
! hashtable cursor
!
[ hashtable>> dup array>> ] [ n>> 2 + ] bi
(inc-hashtable-cursor) <hashtable-cursor> ; inline
-INSTANCE: hashtable-cursor assoc-cursor
-
-M: hashtable-cursor cursor-key-value
- [ n>> ] [ hashtable>> array>> ] bi
- [ nth-unsafe ] [ [ 1 + ] dip nth-unsafe ] 2bi ; inline
-
INSTANCE: hashtable-cursor input-cursor
-M: hashtable-cursor cursor-value-unsafe
- cursor-key-value 2array ; inline
+M: hashtable-cursor cursor-key-value-unsafe
+ [ n>> ] [ hashtable>> array>> ] bi
+ [ nth-unsafe ] [ [ 1 + ] dip nth-unsafe ] 2bi ; inline
INSTANCE: hashtable container
M: zip-cursor inc-cursor ( cursor -- cursor' )
[ keys>> inc-cursor ] [ values>> inc-cursor ] bi <zip-cursor> ; inline
-INSTANCE: zip-cursor assoc-cursor
+INSTANCE: zip-cursor input-cursor
M: zip-cursor cursor-key-value
[ keys>> cursor-value-unsafe ] [ values>> cursor-value-unsafe ] bi ; inline
IN: mason.child.tests
USING: mason.child mason.config tools.test namespaces io kernel sequences ;
-[ { "nmake" "/f" "nmakefile" } ] [
+[ { "nmake" "/f" "nmakefile" "x86-32" } ] [
[
"winnt" target-os set
"x86.32" target-cpu set
continuations debugger io.directories io.files io.launcher
io.pathnames io.encodings.ascii kernel make mason.common mason.config
mason.platform mason.report mason.notify namespaces sequences
-quotations macros system combinators ;
+quotations macros system combinators splitting ;
IN: mason.child
+: nmake-cmd ( -- args )
+ { "nmake" "/f" "nmakefile" }
+ target-cpu get "." split "-" join suffix ;
+
+: gnu-make-cmd ( -- args )
+ gnu-make platform 2array ;
+
: make-cmd ( -- args )
{
- { [ target-os get "winnt" = ] [ { "nmake" "/f" "nmakefile" } ] }
- [ gnu-make platform 2array ]
+ { [ target-os get "winnt" = ] [ nmake-cmd ] }
+ [ gnu-make-cmd ]
} cond ;
: make-vm ( -- )
+PLAF_DLL_OBJS += vm/os-windows-nt-x86.32.o
DLL_PATH=http://factorcode.org/dlls
WINDRES=windres
include vm/Config.windows.nt
+PLAF_DLL_OBJS += vm/os-windows-nt-x86.64.o
DLL_PATH=http://factorcode.org/dlls/64
CC=$(WIN64_PATH)-gcc.exe
WINDRES=$(WIN64_PATH)-windres.exe
{
if(size > ((u64)1 << (sizeof(cell) * 8 - 6))) fatal_error("Heap too large",size);
seg = new segment(align_page(size),true);
- if(!seg) fatal_error("Out of memory in heap allocator",size);
- allocator = new free_list_allocator<code_block>(size,seg->start);
+ if(!seg) fatal_error("Out of memory in code_heap constructor",size);
+
+ cell start = seg->start + seh_area_size;
+
+ allocator = new free_list_allocator<code_block>(seg->end - start,start);
+
+ /* See os-windows-nt-x86.64.cpp for seh_area usage */
+ seh_area = (char *)seg->start;
}
code_heap::~code_heap()
namespace factor
{
+#if defined(WINDOWS) && defined(FACTOR_64)
+ const cell seh_area_size = 1024;
+#else
+ const cell seh_area_size = 0;
+#endif
+
struct code_heap {
/* The actual memory area */
segment *seg;
+ /* Memory area reserved for SEH. Only used on Windows */
+ char *seh_area;
+
/* Memory allocator */
free_list_allocator<code_block> *allocator;
init_objects(&h);
cell data_offset = data->tenured->start - h.data_relocation_base;
- cell code_offset = code->seg->start - h.code_relocation_base;
+ cell code_offset = code->allocator->start - h.code_relocation_base;
fixup_data(data_offset,code_offset);
fixup_code(data_offset,code_offset);
h.version = image_version;
h.data_relocation_base = data->tenured->start;
h.data_size = data->tenured->occupied_space();
- h.code_relocation_base = code->seg->start;
+ h.code_relocation_base = code->allocator->start;
h.code_size = code->allocator->occupied_space();
h.true_object = true_object;
--- /dev/null
+#include "master.hpp"
+
+namespace factor
+{
+
+void factor_vm::c_to_factor_toplevel(cell quot)
+{
+ /* 32-bit Windows SEH is set up in basis/cpu/x86/32/winnt/bootstrap.factor */
+ c_to_factor(quot);
+}
+
+}
--- /dev/null
+#include "master.hpp"
+
+namespace factor {
+
+typedef unsigned char UBYTE;
+
+const UBYTE UNW_FLAG_EHANDLER = 0x1;
+
+struct UNWIND_INFO {
+ UBYTE Version:3;
+ UBYTE Flags:5;
+ UBYTE SizeOfProlog;
+ UBYTE CountOfCodes;
+ UBYTE FrameRegister:4;
+ UBYTE FrameOffset:4;
+ ULONG ExceptionHandler;
+ ULONG ExceptionData[1];
+};
+
+struct seh_data {
+ UNWIND_INFO unwind_info;
+ RUNTIME_FUNCTION func;
+ UBYTE handler[32];
+};
+
+void factor_vm::c_to_factor_toplevel(cell quot)
+{
+ /* The annoying thing about Win64 SEH is that the offsets in
+ * function tables are 32-bit integers, and the exception handler
+ * itself must reside between the start and end pointers, so
+ * we stick everything at the beginning of the code heap and
+ * generate a small trampoline that jumps to the real
+ * exception handler. */
+
+ seh_data *seh_area = (seh_data *)code->seh_area;
+ cell base = code->seg->start;
+
+ /* Should look at generating this with the Factor assembler */
+
+ /* mov rax,0 */
+ seh_area->handler[0] = 0x48;
+ seh_area->handler[1] = 0xb8;
+ seh_area->handler[2] = 0x0;
+ seh_area->handler[3] = 0x0;
+ seh_area->handler[4] = 0x0;
+ seh_area->handler[5] = 0x0;
+ seh_area->handler[6] = 0x0;
+ seh_area->handler[7] = 0x0;
+ seh_area->handler[8] = 0x0;
+ seh_area->handler[9] = 0x0;
+
+ /* jmp rax */
+ seh_area->handler[10] = 0x48;
+ seh_area->handler[11] = 0xff;
+ seh_area->handler[12] = 0xe0;
+
+ /* Store address of exception handler in the operand of the 'mov' */
+ cell handler = (cell)&factor::exception_handler;
+ memcpy(&seh_area->handler[2],&handler,sizeof(cell));
+
+ UNWIND_INFO *unwind_info = &seh_area->unwind_info;
+ unwind_info->Version = 1;
+ unwind_info->Flags = UNW_FLAG_EHANDLER;
+ unwind_info->SizeOfProlog = 0;
+ unwind_info->CountOfCodes = 0;
+ unwind_info->FrameRegister = 0;
+ unwind_info->FrameOffset = 0;
+ unwind_info->ExceptionHandler = (DWORD)((cell)&seh_area->handler[0] - base);
+ unwind_info->ExceptionData[0] = 0;
+
+ RUNTIME_FUNCTION *func = &seh_area->func;
+ func->BeginAddress = 0;
+ func->EndAddress = (DWORD)(code->seg->end - base);
+ func->UnwindData = (DWORD)((cell)&seh_area->unwind_info - base);
+
+ if(!RtlAddFunctionTable(func,1,base))
+ fatal_error("RtlAddFunctionTable() failed",0);
+
+ c_to_factor(quot);
+
+ if(!RtlDeleteFunctionTable(func))
+ fatal_error("RtlDeleteFunctionTable() failed",0);
+}
+
+}
break;
}
- return ExceptionContinueExecution;
+ return 0;
}
VM_C_API LONG exception_handler(PEXCEPTION_RECORD e, void *frame, PCONTEXT c, void *dispatch)
return current_vm()->exception_handler(e,frame,c,dispatch);
}
-void factor_vm::c_to_factor_toplevel(cell quot)
-{
- c_to_factor(quot);
-}
-
void factor_vm::open_console()
{
}