]> gitweb.factorcode.org Git - factor.git/commitdiff
Add context-specific special object table, generalizing catchstack_save and current_c...
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Thu, 18 Mar 2010 09:06:00 +0000 (22:06 +1300)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Thu, 18 Mar 2010 09:06:00 +0000 (22:06 +1300)
18 files changed:
basis/compiler/codegen/codegen.factor
basis/compiler/tests/alien.factor
basis/stack-checker/alien/alien.factor
basis/stack-checker/known-words/known-words.factor
basis/stack-checker/row-polymorphism/row-polymorphism.factor
core/alien/alien.factor
core/bootstrap/primitives.factor
core/bootstrap/stage1.factor
core/continuations/continuations.factor
core/namespaces/namespaces.factor
vm/contexts.cpp
vm/contexts.hpp
vm/objects.cpp
vm/objects.hpp
vm/primitives.cpp
vm/primitives.hpp
vm/slot_visitor.hpp
vm/vm.hpp

index 3edfcc565b39f3792d2b8354a92a9578cc730333..73cfd6b86e8bc29c8330689d91f3ef7bddc32ef4 100755 (executable)
@@ -1,11 +1,12 @@
 ! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces make math math.order math.parser sequences accessors
-kernel kernel.private layouts assocs words summary arrays
-combinators classes.algebra alien alien.c-types
-alien.strings alien.arrays alien.complex alien.libraries sets libc
-continuations.private fry cpu.architecture classes classes.struct locals
-source-files.errors slots parser generic.parser strings
+USING: namespaces make math math.order math.parser sequences
+accessors kernel layouts assocs words summary arrays combinators
+classes.algebra alien alien.private alien.c-types alien.strings
+alien.arrays alien.complex alien.libraries sets libc
+continuations.private fry cpu.architecture classes
+classes.struct locals source-files.errors slots parser
+generic.parser strings quotations
 compiler.errors
 compiler.alien
 compiler.constants
@@ -461,22 +462,6 @@ M: ##alien-indirect generate-insn
         box-parameters
     ] with-param-regs ;
 
-TUPLE: callback-context ;
-
-: current-callback ( -- id ) 2 special-object ;
-
-: wait-to-return ( token -- )
-    dup current-callback eq? [
-        drop
-    ] [
-        yield-hook get call( -- ) wait-to-return
-    ] if ;
-
-: do-callback ( quot token -- )
-    init-catchstack
-    [ 2 set-special-object call ] keep
-    wait-to-return ; inline
-
 : callback-return-quot ( ctype -- quot )
     return>> {
         { [ dup void? ] [ drop [ ] ] }
@@ -488,12 +473,10 @@ TUPLE: callback-context ;
     parameters>> [ c-type c-type-boxer-quot ] map spread>quot ;
 
 : wrap-callback-quot ( params -- quot )
-    [
-        [ callback-prep-quot ]
-        [ quot>> ]
-        [ callback-return-quot ] tri 3append ,
-        [ callback-context new do-callback ] %
-    ] [ ] make ;
+    [ callback-prep-quot ] [ quot>> ] [ callback-return-quot ] tri 3append
+     yield-hook get
+     '[ _ _ do-callback ]
+     >quotation ;
 
 M: ##alien-callback generate-insn
     params>>
index acb5555bc376485ebc954f464713c6623f2243c6..ad8dac3ef95c285042fa9c73be1f4480fa5b2879 100755 (executable)
@@ -330,26 +330,15 @@ FUNCTION: ulonglong ffi_test_38 ( ulonglong x, ulonglong y ) ;
 
 : callback-3 ( -- callback ) void { } "cdecl" [ 5 "x" set ] alien-callback ;
 
-[ t ] [
-    namestack*
-    3 "x" set callback-3 callback_test_1
-    namestack* eq?
-] unit-test
-
-[ 5 ] [
+[ t 3 5 ] [
     [
-        3 "x" set callback-3 callback_test_1 "x" get
+        namestack*
+        3 "x" set callback-3 callback_test_1
+        namestack* eq?
+        "x" get "x" get-global
     ] with-scope
 ] unit-test
 
-: callback-4 ( -- callback )
-    void { } "cdecl" [ "Hello world" write ] alien-callback
-    gc ;
-
-[ "Hello world" ] [
-    [ callback-4 callback_test_1 ] with-string-writer
-] unit-test
-
 : callback-5 ( -- callback )
     void { } "cdecl" [ gc ] alien-callback ;
 
index 81d8a93240dfc2ce867f3bfd0fdf9222671ae718..9039c5d3f0e4c59ac4773a49134520455778eaab 100644 (file)
@@ -1,9 +1,10 @@
 ! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel sequences accessors combinators math namespaces
-init sets words assocs alien.libraries alien alien.c-types
-cpu.architecture fry stack-checker.backend stack-checker.errors
-stack-checker.visitor stack-checker.dependencies ;
+init sets words assocs alien.libraries alien alien.private
+alien.c-types cpu.architecture fry stack-checker.backend
+stack-checker.errors stack-checker.visitor
+stack-checker.dependencies ;
 IN: stack-checker.alien
 
 TUPLE: alien-node-params return parameters abi in-d out-d ;
index 2c08533ebbd20e87b648a48dbc73af941c812d46..d0cbb05919210556a66597c0206ea35f08dcc7c9 100644 (file)
@@ -509,6 +509,11 @@ M: bad-executable summary
 
 \ set-special-object { object fixnum } { } define-primitive
 
+\ context-object { fixnum } { object } define-primitive
+\ context-object make-flushable
+
+\ set-context-object { object fixnum } { } define-primitive
+
 \ (exists?) { string } { object } define-primitive
 
 \ minor-gc { } { } define-primitive
index d91c766fea4ed30bbcb50a9e7cac71f07eb9761c..1b8bd8faeda7586d33887e650e034f844b4c71f3 100644 (file)
@@ -4,7 +4,6 @@ continuations effects fry kernel locals math math.order namespaces
 quotations sequences splitting
 stack-checker.backend
 stack-checker.errors
-stack-checker.known-words
 stack-checker.state
 stack-checker.values
 stack-checker.visitor ;
index 631fdcfc9303d9d4658e2988af04a396285193e0..191886393a3537c25e2b4b77c2c1ad85e3508caf 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2004, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs kernel math namespaces sequences system
-kernel.private byte-arrays byte-vectors arrays init ;
+kernel.private byte-arrays byte-vectors arrays init
+continuations.private ;
 IN: alien
 
 PREDICATE: pinned-alien < alien underlying>> not ;
@@ -83,6 +84,8 @@ ERROR: alien-assembly-error code ;
 : alien-assembly ( args... return parameters abi quot -- return... )
     dup alien-assembly-error ;
 
+<PRIVATE
+
 ! Callbacks are registered in a global hashtable. Note that they
 ! are also pinned in a special callback area, so clearing this
 ! hashtable will not reclaim callbacks. It should only be
@@ -91,8 +94,29 @@ SYMBOL: callbacks
 
 [ H{ } clone callbacks set-global ] "alien" add-startup-hook
 
-<PRIVATE
+! Every context object in the VM is identified from the Factor
+! side by a unique identifier
+TUPLE: context-id < identity-tuple ;
+
+C: <context-id> context-id
+
+: context-id ( -- id ) 2 context-object ;
+
+: set-context-id ( id -- ) 2 set-context-object ;
+
+: wait-to-return ( yield-quot id -- )
+    dup context-id eq?
+    [ 2drop ] [ over call( -- ) wait-to-return ] if ;
+
+! Used by compiler.codegen to wrap callback bodies
+: do-callback ( callback-quot yield-quot -- )
+    init-namespaces
+    init-catchstack
+    <context-id>
+    [ set-context-id drop call ] [ wait-to-return drop ] 3bi ; inline
 
+! A utility for defining global variables that are recompiled in
+! every session
 TUPLE: expiry-check object alien ;
 
 : recompute-value? ( check -- ? )
index 2772b68875d583cb9401ae7fc914c0cdf3bd59ab..19a179a6b1baecad0e81f3f07b8acd793d260255 100644 (file)
@@ -447,8 +447,10 @@ tuple
     { "call-clear" "kernel.private" "primitive_call_clear" (( quot -- * )) }
     { "check-datastack" "kernel.private" "primitive_check_datastack" (( array in# out# -- ? )) }
     { "compute-identity-hashcode" "kernel.private" "primitive_compute_identity_hashcode" (( obj -- )) }
+    { "context-object" "kernel.private" "primitive_context_object" (( n -- obj )) }
     { "innermost-frame-executing" "kernel.private" "primitive_innermost_stack_frame_executing" (( callstack -- obj )) }
     { "innermost-frame-scan" "kernel.private" "primitive_innermost_stack_frame_scan" (( callstack -- n )) }
+    { "set-context-object" "kernel.private" "primitive_set_context_object" (( obj n -- )) }
     { "set-datastack" "kernel.private" "primitive_set_datastack" (( ds -- )) }
     { "set-innermost-frame-quot" "kernel.private" "primitive_set_innermost_stack_frame_quot" (( n callstack -- )) }
     { "set-retainstack" "kernel.private" "primitive_set_retainstack" (( rs -- )) }
index 78658206de42af07531195fa573d21ab40a63634..41218fff6d395041587ae96ee98aa3fb14e96c63 100644 (file)
@@ -40,7 +40,7 @@ load-help? off
             run-file
         ] [
             "Cannot find " write write "." print
-            "Please move " write image write " to the same directory as the Factor sources," print
+            "Please move " write image write " into the same directory as the Factor sources," print
             "and try again." print
             1 (exit)
         ] if
index 687f7153a175182892139173f7a573f56c518808..cfceb1f71574ba1e3e69a2ef4fc8ecea9df6738e 100644 (file)
@@ -13,7 +13,7 @@ SYMBOL: restarts
 <PRIVATE
 
 : catchstack* ( -- catchstack )
-    1 special-object { vector } declare ; inline
+    1 context-object { vector } declare ; inline
 
 : >c ( continuation -- ) catchstack* push ;
 
@@ -23,13 +23,14 @@ SYMBOL: restarts
 : dummy-1 ( -- obj ) f ;
 : dummy-2 ( obj -- obj ) dup drop ;
 
-: init-catchstack ( -- ) V{ } clone 1 set-special-object ;
+: catchstack ( -- catchstack ) catchstack* clone ; inline
 
-PRIVATE>
+: set-catchstack ( catchstack -- )
+    >vector 1 set-context-object ; inline
 
-: catchstack ( -- catchstack ) catchstack* clone ; inline
+: init-catchstack ( -- ) f set-catchstack ;
 
-: set-catchstack ( catchstack -- ) >vector 1 set-special-object ; inline
+PRIVATE>
 
 TUPLE: continuation data call retain name catch ;
 
@@ -39,14 +40,12 @@ C: <continuation> continuation
     datastack callstack retainstack namestack catchstack
     <continuation> ;
 
+<PRIVATE
+
 : >continuation< ( continuation -- data call retain name catch )
-    {
-        [ data>>   ]
-        [ call>>   ]
-        [ retain>> ]
-        [ name>>   ]
-        [ catch>>  ]
-    } cleave ;
+    { [ data>> ] [ call>> ] [ retain>> ] [ name>> ] [ catch>> ] } cleave ;
+
+PRIVATE>
 
 : ifcc ( capture restore -- )
     [ dummy-1 continuation ] 2dip [ dummy-2 ] prepose ?if ; inline
@@ -172,7 +171,7 @@ M: condition compute-restarts
 <PRIVATE
 
 : init-error-handler ( -- )
-    V{ } clone set-catchstack
+    init-catchstack
     ! VM calls on error
     [
         ! 63 = self
index 40b1db8a3f39a83fcfb1955cd85ce3aaf3ab23e8..a100c2d15fca015dafde904c4f8f7b9adb508fe6 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2003, 2008 Slava Pestov.
+! Copyright (C) 2003, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel vectors sequences hashtables
 arrays kernel.private math strings assocs ;
@@ -6,7 +6,7 @@ IN: namespaces
 
 <PRIVATE
 
-: namestack* ( -- namestack ) 0 special-object { vector } declare ; inline
+: namestack* ( -- namestack ) 0 context-object { vector } declare ; inline
 : >n ( namespace -- ) namestack* push ;
 : ndrop ( -- ) namestack* pop* ;
 
@@ -14,7 +14,7 @@ PRIVATE>
 
 : namespace ( -- namespace ) namestack* last ; inline
 : namestack ( -- namestack ) namestack* clone ;
-: set-namestack ( namestack -- ) >vector 0 set-special-object ;
+: set-namestack ( namestack -- ) >vector 0 set-context-object ;
 : global ( -- g ) 21 special-object { hashtable } declare ; inline
 : init-namespaces ( -- ) global 1array set-namestack ;
 : get ( variable -- value ) namestack* assoc-stack ; inline
index 394d14e55dc2a309ab38e84f80e3fc6e8331da97..1079c572d2de756ed15b54de6d9e45ec28b66975 100644 (file)
@@ -10,12 +10,26 @@ context::context(cell ds_size, cell rs_size) :
        retainstack(0),
        datastack_region(new segment(ds_size,false)),
        retainstack_region(new segment(rs_size,false)),
-       catchstack_save(0),
-       current_callback_save(0),
        next(NULL)
 {
        reset_datastack();
        reset_retainstack();
+       reset_context_objects();
+}
+
+void context::reset_datastack()
+{
+       datastack = datastack_region->start - sizeof(cell);
+}
+
+void context::reset_retainstack()
+{
+       retainstack = retainstack_region->start - sizeof(cell);
+}
+
+void context::reset_context_objects()
+{
+       memset_cell(context_objects,false_object,context_object_count * sizeof(cell));
 }
 
 context *factor_vm::alloc_context()
@@ -47,12 +61,9 @@ void factor_vm::nest_stacks()
        new_ctx->callstack_bottom = (stack_frame *)-1;
        new_ctx->callstack_top = (stack_frame *)-1;
 
-       /* save per-callback special_objects */
-       new_ctx->current_callback_save = special_objects[OBJ_CURRENT_CALLBACK];
-       new_ctx->catchstack_save = special_objects[OBJ_CATCHSTACK];
-
        new_ctx->reset_datastack();
        new_ctx->reset_retainstack();
+       new_ctx->reset_context_objects();
 
        new_ctx->next = ctx;
        ctx = new_ctx;
@@ -66,10 +77,6 @@ void nest_stacks(factor_vm *parent)
 /* called when leaving a compiled callback */
 void factor_vm::unnest_stacks()
 {
-       /* restore per-callback special_objects */
-       special_objects[OBJ_CURRENT_CALLBACK] = ctx->current_callback_save;
-       special_objects[OBJ_CATCHSTACK] = ctx->catchstack_save;
-
        context *old_ctx = ctx;
        ctx = old_ctx->next;
        dealloc_context(old_ctx);
@@ -89,6 +96,19 @@ void factor_vm::init_stacks(cell ds_size_, cell rs_size_)
        unused_contexts = NULL;
 }
 
+void factor_vm::primitive_context_object()
+{
+       fixnum n = untag_fixnum(ctx->peek());
+       ctx->replace(ctx->context_objects[n]);
+}
+
+void factor_vm::primitive_set_context_object()
+{
+       fixnum n = untag_fixnum(ctx->pop());
+       cell value = ctx->pop();
+       ctx->context_objects[n] = value;
+}
+
 bool factor_vm::stack_to_array(cell bottom, cell top)
 {
        fixnum depth = (fixnum)(top - bottom + sizeof(cell));
index 9ba9bb313cf520daa45a91160becc6ff2aaf50c8..e555bd4a92ec41099f6b38396abafcd2a360f868 100644 (file)
@@ -1,6 +1,14 @@
 namespace factor
 {
 
+static const cell context_object_count = 10;
+
+enum context_object {
+       OBJ_NAMESTACK,
+       OBJ_CATCHSTACK,
+       OBJ_CONTEXT_ID,
+};
+
 /* Assembly code makes assumptions about the layout of this struct */
 struct context {
        /* C stack pointer on entry */
@@ -19,13 +27,16 @@ struct context {
        /* memory region holding current retain stack */
        segment *retainstack_region;
 
-       /* saved special_objects slots on entry to callback */
-       cell catchstack_save;
-       cell current_callback_save;
+       /* context-specific special objects, accessed by context-object and
+       set-context-object primitives */
+       cell context_objects[context_object_count];
 
        context *next;
 
        context(cell ds_size, cell rs_size);
+       void reset_datastack();
+       void reset_retainstack();
+       void reset_context_objects();
 
        cell peek()
        {
@@ -50,16 +61,6 @@ struct context {
                replace(tagged);
        }
 
-       void reset_datastack()
-       {
-               datastack = datastack_region->start - sizeof(cell);
-       }
-
-       void reset_retainstack()
-       {
-               retainstack = retainstack_region->start - sizeof(cell);
-       }
-
        static const cell stack_reserved = (64 * sizeof(cell));
 
        void fix_stacks()
index f1201c4de7c4c759a893042fc88eba50433e3c9f..6b007f5d420f220c13130dcbd5f582df93dc8c53 100644 (file)
@@ -5,15 +5,15 @@ namespace factor
 
 void factor_vm::primitive_special_object()
 {
-       fixnum e = untag_fixnum(ctx->peek());
-       ctx->replace(special_objects[e]);
+       fixnum n = untag_fixnum(ctx->peek());
+       ctx->replace(special_objects[n]);
 }
 
 void factor_vm::primitive_set_special_object()
 {
-       fixnum e = untag_fixnum(ctx->pop());
+       fixnum n = untag_fixnum(ctx->pop());
        cell value = ctx->pop();
-       special_objects[e] = value;
+       special_objects[n] = value;
 }
 
 void factor_vm::primitive_identity_hashcode()
index 2d777ac5165454788600daafad79b11779f55f18..772863d3f1f02cd35c74e33dd9848d6a28ce9c64 100644 (file)
@@ -4,11 +4,7 @@ namespace factor
 static const cell special_object_count = 70;
 
 enum special_object {
-       OBJ_NAMESTACK,             /* used by library only */
-       OBJ_CATCHSTACK,            /* used by library only, per-callback */
-
-       OBJ_CURRENT_CALLBACK = 2,  /* used by library only, per-callback */
-       OBJ_WALKER_HOOK,           /* non-local exit hook, used by library only */
+       OBJ_WALKER_HOOK = 3,       /* non-local exit hook, used by library only */
        OBJ_CALLCC_1,              /* used to pass the value in callcc1 */
 
        ERROR_HANDLER_QUOT = 5,    /* quotation called when VM throws an error */
index be9d5c6ff6e2d809731b2fb2ec4943093b22e475..aa1e10f5a5f647df2401468da48627e57778d346 100644 (file)
@@ -47,6 +47,7 @@ PRIMITIVE(code_blocks)
 PRIMITIVE(code_room)
 PRIMITIVE(compact_gc)
 PRIMITIVE(compute_identity_hashcode)
+PRIMITIVE(context_object)
 PRIMITIVE(data_room)
 PRIMITIVE(datastack)
 PRIMITIVE(die)
@@ -111,6 +112,7 @@ PRIMITIVE(resize_string)
 PRIMITIVE(retainstack)
 PRIMITIVE(save_image)
 PRIMITIVE(save_image_and_exit)
+PRIMITIVE(set_context_object)
 PRIMITIVE(set_datastack)
 PRIMITIVE(set_innermost_stack_frame_quot)
 PRIMITIVE(set_retainstack)
index 520df423a14833de4085e1ec079c012328e9d7e2..a36050323f5ac1a08565b72e92ac1ac44ece09f3 100644 (file)
@@ -43,6 +43,7 @@ DECLARE_PRIMITIVE(code_blocks)
 DECLARE_PRIMITIVE(code_room)
 DECLARE_PRIMITIVE(compact_gc)
 DECLARE_PRIMITIVE(compute_identity_hashcode)
+DECLARE_PRIMITIVE(context_object)
 DECLARE_PRIMITIVE(data_room)
 DECLARE_PRIMITIVE(datastack)
 DECLARE_PRIMITIVE(die)
@@ -107,6 +108,7 @@ DECLARE_PRIMITIVE(resize_string)
 DECLARE_PRIMITIVE(retainstack)
 DECLARE_PRIMITIVE(save_image)
 DECLARE_PRIMITIVE(save_image_and_exit)
+DECLARE_PRIMITIVE(set_context_object)
 DECLARE_PRIMITIVE(set_datastack)
 DECLARE_PRIMITIVE(set_innermost_stack_frame_quot)
 DECLARE_PRIMITIVE(set_retainstack)
index 0ab9cc171d703f36e0e4dee65f09c892f87bc822..e8ff7e30d25d567b86466c3db158d6dc5e05e909 100644 (file)
@@ -26,6 +26,7 @@ template<typename Visitor> struct slot_visitor {
 
        cell visit_pointer(cell pointer);
        void visit_handle(cell *handle);
+       void visit_object_array(cell *start, cell *end);
        void visit_slots(object *ptr, cell payload_start);
        void visit_slots(object *ptr);
        void visit_stack_elements(segment *region, cell *top);
@@ -55,6 +56,12 @@ void slot_visitor<Visitor>::visit_handle(cell *handle)
        *handle = visit_pointer(*handle);
 }
 
+template<typename Visitor>
+void slot_visitor<Visitor>::visit_object_array(cell *start, cell *end)
+{
+       while(start < end) visit_handle(start++);
+}
+
 template<typename Visitor>
 void slot_visitor<Visitor>::visit_slots(object *ptr, cell payload_start)
 {
@@ -64,7 +71,7 @@ void slot_visitor<Visitor>::visit_slots(object *ptr, cell payload_start)
        if(slot != end)
        {
                slot++;
-               for(; slot < end; slot++) visit_handle(slot);
+               visit_object_array(slot,end);
        }
 }
 
@@ -77,8 +84,7 @@ void slot_visitor<Visitor>::visit_slots(object *ptr)
 template<typename Visitor>
 void slot_visitor<Visitor>::visit_stack_elements(segment *region, cell *top)
 {
-       for(cell *ptr = (cell *)region->start; ptr <= top; ptr++)
-               visit_handle(ptr);
+       visit_object_array((cell *)region->start,top + 1);
 }
 
 template<typename Visitor>
@@ -88,11 +94,7 @@ void slot_visitor<Visitor>::visit_data_roots()
        std::vector<data_root_range>::const_iterator end = parent->data_roots.end();
 
        for(; iter < end; iter++)
-       {
-               data_root_range r = *iter;
-               for(cell index = 0; index < r.len; index++)
-                       visit_handle(r.start + index);
-       }
+               visit_object_array(iter->start,iter->start + iter->len);
 }
 
 template<typename Visitor>
@@ -162,8 +164,7 @@ void slot_visitor<Visitor>::visit_roots()
        visit_callback_roots();
        visit_literal_table_roots();
 
-       for(cell i = 0; i < special_object_count; i++)
-               visit_handle(&parent->special_objects[i]);
+       visit_object_array(parent->special_objects,parent->special_objects + special_object_count);
 }
 
 template<typename Visitor>
@@ -175,9 +176,7 @@ void slot_visitor<Visitor>::visit_contexts()
        {
                visit_stack_elements(ctx->datastack_region,(cell *)ctx->datastack);
                visit_stack_elements(ctx->retainstack_region,(cell *)ctx->retainstack);
-
-               visit_handle(&ctx->catchstack_save);
-               visit_handle(&ctx->current_callback_save);
+               visit_object_array(ctx->context_objects,ctx->context_objects + context_object_count);
 
                ctx = ctx->next;
        }
index 714794aa32606a530262ff689ce96339fda8be1b..f20145b43f2a58cfde9d0782711be5f29aa19a82 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -18,7 +18,8 @@ struct factor_vm
        cell cards_offset;
        cell decks_offset;
 
-       /* TAGGED user environment data; see getenv/setenv prims */
+       /* Various special objects, accessed by special-object and
+       set-special-object primitives */
        cell special_objects[special_object_count];
 
        /* Data stack and retain stack sizes */
@@ -100,6 +101,8 @@ struct factor_vm
        void nest_stacks();
        void unnest_stacks();
        void init_stacks(cell ds_size_, cell rs_size_);
+       void primitive_context_object();
+       void primitive_set_context_object();
        bool stack_to_array(cell bottom, cell top);
        cell array_to_stack(array *array, cell bottom);
        void primitive_datastack();