M: x86.32 %begin-callback ( -- )
0 save-vm-ptr
+ ESP 4 [+] 0 MOV
"begin_callback" f %alien-invoke ;
M: x86.32 %alien-callback ( quot -- )
[
jit-load-vm
ESP [] vm-reg MOV
- "begin_callback" jit-call
-
- ! load quotation - EBP is ctx-reg so it will get clobbered
- ! later on
EAX EBP 8 [+] MOV
+ ESP 4 [+] EAX MOV
+ "begin_callback" jit-call
jit-load-vm
jit-load-context
M: x86.64 %begin-callback ( -- )
param-reg-0 %mov-vm-ptr
+ param-reg-1 0 MOV
"begin_callback" f %alien-invoke ;
M: x86.64 %alien-callback ( quot -- )
: jit-call-quot ( -- ) arg1 quot-entry-point-offset [+] CALL ;
[
- nv-reg arg1 MOV
-
+ arg2 arg1 MOV
arg1 vm-reg MOV
"begin_callback" jit-call
jit-restore-context
! call the quotation
- arg1 nv-reg MOV
+ arg1 return-reg MOV
jit-call-quot
jit-save-context
\ code-room { } { byte-array } define-primitive \ code-room make-flushable
\ compact-gc { } { } define-primitive
\ compute-identity-hashcode { object } { } define-primitive
-\ context { } { c-ptr } define-primitive \ context make-flushable
\ context-object { fixnum } { object } define-primitive \ context-object make-flushable
\ context-object-for { fixnum c-ptr } { object } define-primitive \ context-object-for make-flushable
\ current-callback { } { fixnum } define-primitive \ current-callback make-flushable
! Wrap sub-primitives; we don't want them inlined into callers
! since their behavior depends on what frames are on the callstack
+: context ( -- context )
+ 2 context-object ; inline
+
: set-context ( obj context -- obj' )
- (set-context) ;
+ (set-context) ; inline
: start-context ( obj quot: ( obj -- * ) -- obj' )
- (start-context) ;
+ (start-context) ; inline
: set-context-and-delete ( obj context -- * )
- (set-context-and-delete) ;
+ (set-context-and-delete) ; inline
: start-context-and-delete ( obj quot: ( obj -- * ) -- * )
- (start-context-and-delete) ;
+ (start-context-and-delete) ; inline
! Context introspection
: namestack-for ( context -- namestack )
{ "system-micros" "system" "primitive_system_micros" (( -- us )) }
{ "(sleep)" "threads.private" "primitive_sleep" (( nanos -- )) }
{ "callstack-for" "threads.private" "primitive_callstack_for" (( context -- array )) }
- { "context" "threads.private" "primitive_context" (( -- context )) }
{ "context-object-for" "threads.private" "primitive_context_object_for" (( n context -- obj )) }
{ "datastack-for" "threads.private" "primitive_datastack_for" (( context -- array )) }
{ "retainstack-for" "threads.private" "primitive_retainstack_for" (( context -- array )) }
return new_context;
}
+void factor_vm::init_context(context *ctx)
+{
+ ctx->context_objects[OBJ_CONTEXT] = allot_alien(ctx);
+}
+
context *new_context(factor_vm *parent)
{
- return parent->new_context();
+ context *new_context = parent->new_context();
+ parent->init_context(new_context);
+ return new_context;
}
void factor_vm::delete_context(context *old_context)
parent->delete_context(old_context);
}
-void factor_vm::begin_callback()
+cell factor_vm::begin_callback(cell quot_)
{
+ data_root<object> quot(quot_,this);
+
ctx->reset();
spare_ctx = new_context();
callback_ids.push_back(callback_id++);
+
+ init_context(ctx);
+
+ return quot.value();
}
-void begin_callback(factor_vm *parent)
+cell begin_callback(factor_vm *parent, cell quot)
{
- parent->begin_callback();
+ return parent->begin_callback(quot);
}
void factor_vm::end_callback()
ctx->retainstack += sizeof(cell) * count;
}
-void factor_vm::primitive_context()
-{
- ctx->push(allot_alien(ctx));
-}
-
}
enum context_object {
OBJ_NAMESTACK,
OBJ_CATCHSTACK,
+ OBJ_CONTEXT,
};
static const cell stack_reserved = 1024;
VM_C_API context *new_context(factor_vm *parent);
VM_C_API void delete_context(factor_vm *parent, context *old_context);
-VM_C_API void begin_callback(factor_vm *parent);
+VM_C_API cell begin_callback(factor_vm *parent, cell quot);
VM_C_API void end_callback(factor_vm *parent);
}
_(code_room) \
_(compact_gc) \
_(compute_identity_hashcode) \
- _(context) \
_(context_object) \
_(context_object_for) \
_(current_callback) \
// contexts
context *new_context();
+ void init_context(context *ctx);
void delete_context(context *old_context);
void init_contexts(cell datastack_size_, cell retainstack_size_, cell callstack_size_);
void delete_contexts();
- void begin_callback();
+ cell begin_callback(cell quot);
void end_callback();
void primitive_current_callback();
void primitive_context_object();
void primitive_set_retainstack();
void primitive_check_datastack();
void primitive_load_locals();
- void primitive_context();
template<typename Iterator> void iterate_active_callstacks(Iterator &iter)
{