[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Help-smalltalk] [PATCH] Deferred variable bindings, part 3/3
From: |
Paolo Bonzini |
Subject: |
[Help-smalltalk] [PATCH] Deferred variable bindings, part 3/3 |
Date: |
Fri, 24 Aug 2007 11:30:22 +0200 |
User-agent: |
Thunderbird 2.0.0.6 (Macintosh/20070728) |
This finishes the implementation of deferred variable bindings, allowing
code like this:
Eval [
PackageLoader fileInPackage: 'Iconv'.
I18N.EncodedStream blahblah
]
which previously was not allowed, because I18N was not declared at the
beginning of the eval.
It is probably now time to say that implicit temporaries cost a lot in
terms of performance, and this only got worse with deferred variable
bindings:
Eval [ Time millisecondsToRun: [ 1000000 timesRepeat: [ x := 5 ]]]
918
However, you can recover performance by using a temporary inside an Eval:
Eval [ | x | Time millisecondsToRun: [ 1000000 timesRepeat: [ x := 5 ]]]
116
Using a temporary in the inner block:
Eval [ Time millisecondsToRun: [ | x | 1000000 timesRepeat: [ x := 5 ]]]
104
Using a temporary that disables compiler optimization of #timesRepeat:
Eval [ Time millisecondsToRun: [ 1000000 timesRepeat: [ | x | x := 5 ]]]
314
Note that temporaries outside Evals are ignored; otherwise the nice
behavior of temporaries persisting through different invocations would
not be possible.
Paolo
2007-08-24 Paolo Bonzini <address@hidden>
* kernel/DeferBinding.st: Add path variable and #resolvePathFrom:
method.
* libgst/comp.c: Create deferred variable bindings with a path.
Adjust calls to _gst_find_variable_binding.
* libgst/dict.c: Add path variable to DeferredVariableBinding.
* libgst/dict.h: Add path variable to struct
gst_deferred_variable_binding.
* libgst/sym.h: Remove last parameter from
_gst_find_variable_binding.
* libgst/sym.c: Assume last parameter of _gst_find_variable_binding
to be true. Adjust call to _gst_make_deferred_binding_constant.
* libgst/tree.h: Adjust last parameter of
_gst_make_deferred_binding_constant.
* libgst/tree.c: Turn last parameter of _gst_find_variable_binding
into a tree. Support new constant types in _gst_print_tree.
* looking for address@hidden/smalltalk--devo--2.2--patch-534 to compare with
* comparing to address@hidden/smalltalk--devo--2.2--patch-534
M kernel/DeferBinding.st
M libgst/comp.c
M libgst/dict.c
M libgst/sym.c
M libgst/sym.h
M libgst/dict.h
M libgst/tree.c
M libgst/tree.h
* modified files
--- orig/kernel/DeferBinding.st
+++ mod/kernel/DeferBinding.st
@@ -32,7 +32,7 @@
LookupKey subclass: #DeferredVariableBinding
- instanceVariableNames: 'class defaultDictionary association'
+ instanceVariableNames: 'class defaultDictionary association path'
classVariableNames: ''
poolDictionaries: ''
category: 'Language-Data types'
@@ -47,24 +47,39 @@ in the scope of a given class are used.'
!DeferredVariableBinding class methodsFor: 'basic'!
+key: aSymbol class: aClass defaultDictionary: aDictionary path: anArray
+ ^(self key: aSymbol)
+ class: aClass;
+ defaultDictionary: aDictionary;
+ path: anArray;
+ yourself!
+
key: aSymbol class: aClass defaultDictionary: aDictionary
^(self key: aSymbol)
class: aClass;
defaultDictionary: aDictionary;
+ path: #();
yourself! !
!DeferredVariableBinding methodsFor: 'basic'!
value
"Answer a new instance of the receiver with the given key and value"
- association isNil ifTrue: [ association := self resolveBinding ].
+ association isNil
+ ifTrue: [ association := self resolvePathFrom: self resolveBinding ].
^association value
!
value: anObject
"Answer a new instance of the receiver with the given key and value"
- association isNil ifTrue: [ association := self resolveBinding ].
+ association isNil
+ ifTrue: [ association := self resolvePathFrom: self resolveBinding ].
association value: anObject
+!
+
+path
+ "Answer the path followed after resolving the first key."
+ ^path
! !
@@ -77,6 +92,25 @@ class: aClass
defaultDictionary: aDictionary
defaultDictionary := aDictionary!
+path: anArray
+ path := anArray!
+
+resolvePathFrom: assoc
+ "Given the resolution of the first key, resolve the rest of the path.
+ The final element might be put in Undeclared, the ones in the middle
+ instead must exist."
+ | pathAssoc |
+ path isEmpty ifTrue: [ ^assoc ].
+ pathAssoc := assoc.
+ 1 to: path size - 1 do: [ :each |
+ pathAssoc := pathAssoc value associationAt: (path at: each) ].
+ ^pathAssoc value
+ associationAt: path last
+ ifAbsent: [
+ Undeclared
+ at: path last put: nil;
+ associationAt: path last ]!
+
resolveBinding
"Look for a pool dictionary of class that includes the key. If not found,
add the variable to the defaultDictionary. If already bound, reuse the
@@ -109,10 +143,16 @@ resolveBinding
!DeferredVariableBinding methodsFor: 'storing'!
-storeOn: aStream
+printOn: aStream
"Put on aStream some Smalltalk code compiling to the receiver"
- aStream nextPut: $#.
aStream nextPut: ${.
aStream nextPutAll: self key.
+ self path do: [ :each | aStream nextPut: $.; nextPutAll: each ].
aStream nextPut: $}
+!
+
+storeOn: aStream
+ "Put on aStream some Smalltalk code compiling to the receiver"
+ aStream nextPut: $#.
+ self printOn: aStream
! !
--- orig/libgst/comp.c
+++ mod/libgst/comp.c
@@ -2065,13 +2065,26 @@ equal_constant (OOP oop,
{
gst_deferred_variable_binding binding =
(gst_deferred_variable_binding) OOP_TO_OBJ (oop);
- if (binding->key == constExpr->v_const.val.oopVal)
- return (true);
+ gst_object path = OOP_TO_OBJ (binding->path);
+ int i, size = NUM_OOPS (path);
+ OOP *pKey;
+ tree_node varNode = constExpr->v_const.val.aVal;
+
+ /* Use <= because we test the key first. */
+ for (i = 0, pKey = &binding->key; i <= size; pKey = &path->data[i++])
+ {
+ if (!varNode
+ || *pKey != _gst_intern_string (varNode->v_list.name))
+ return (false);
+
+ varNode = varNode->v_list.next;
+ pKey = &path->data[i];
+ }
}
break;
case CONST_BINDING:
- constExpr = _gst_find_variable_binding (constExpr->v_const.val.aVal,
false);
+ constExpr = _gst_find_variable_binding (constExpr->v_const.val.aVal);
if (!constExpr)
return (false);
@@ -2184,18 +2197,36 @@ _gst_make_constant_oop (tree_node constE
case CONST_DEFERRED_BINDING:
{
gst_deferred_variable_binding dvb;
- result = instantiate (_gst_deferred_variable_binding_class,
&resultOOP);
- dvb = (gst_deferred_variable_binding) result;
- dvb->key = constExpr->v_const.val.oopVal;
+ tree_node varNode = constExpr->v_const.val.aVal;
+
+ incPtr = INC_SAVE_POINTER ();
+ dvb = (gst_deferred_variable_binding)
+ instantiate (_gst_deferred_variable_binding_class, &resultOOP);
+ INC_ADD_OOP (resultOOP);
+
+ dvb->key = _gst_intern_string (varNode->v_list.name);
dvb->class = _gst_this_class;
dvb->defaultDictionary = _gst_get_undeclared_dictionary ();
dvb->association = _gst_nil_oop;
+
+ varNode = varNode->v_list.next;
+ if (varNode)
+ {
+ int i, size = list_length (varNode);
+ OOP arrayOOP;
+ gst_object array =
+ instantiate_with (_gst_array_class, size, &arrayOOP);
+
+ dvb->path = arrayOOP;
+ for (i = 0; i < size; i++, varNode = varNode->v_list.next)
+ array->data[i] = _gst_intern_string (varNode->v_list.name);
+ }
+
return (resultOOP);
}
case CONST_BINDING:
- subexpr = _gst_find_variable_binding (constExpr->v_const.val.aVal,
- false);
+ subexpr = _gst_find_variable_binding (constExpr->v_const.val.aVal);
if (!subexpr)
{
_gst_errorf_at (constExpr->location.first_line,
--- orig/libgst/dict.c
+++ mod/libgst/dict.c
@@ -395,8 +395,8 @@ static const class_definition class_info
"LookupKey", "key", NULL, NULL },
{&_gst_deferred_variable_binding_class, &_gst_lookup_key_class,
- ISP_FIXED, true, 3,
- "DeferredVariableBinding", "class defaultDictionary association",
+ ISP_FIXED, true, 4,
+ "DeferredVariableBinding", "class defaultDictionary association path",
NULL, NULL },
{&_gst_association_class, &_gst_lookup_key_class,
--- orig/libgst/dict.h
+++ mod/libgst/dict.h
@@ -171,6 +171,7 @@ typedef struct gst_deferred_variable_bin
OOP class;
OOP defaultDictionary;
OOP association;
+ OOP path;
}
*gst_deferred_variable_binding;
--- orig/libgst/sym.c
+++ mod/libgst/sym.c
@@ -573,7 +573,7 @@ _gst_pop_temporaries_dictionary (OOP dic
tree_node
-_gst_find_variable_binding (tree_node list, mst_Boolean declare_temporary)
+_gst_find_variable_binding (tree_node list)
{
OOP symbol, root, assocOOP;
tree_node elt;
@@ -606,10 +606,8 @@ _gst_find_variable_binding (tree_node li
/* For temporaries, make a deferred binding so that we can try using
a global variable. Unlike namespaces, the temporaries dictionary
does not know anything about Undeclared. */
- else if (_gst_use_undeclared == UNDECLARED_TEMPORARIES
- && !list->v_list.next
- && declare_temporary)
- return _gst_make_deferred_binding_constant (&list->location, symbol);
+ else if (_gst_use_undeclared == UNDECLARED_TEMPORARIES)
+ return _gst_make_deferred_binding_constant (&list->location, list);
else
return NULL;
@@ -686,7 +684,7 @@ _gst_find_variable (symbol_entry * se,
return (true);
}
- resolved = _gst_find_variable_binding (list, true);
+ resolved = _gst_find_variable_binding (list);
if (!resolved)
return (false);
--- orig/libgst/sym.h
+++ mod/libgst/sym.h
@@ -222,8 +222,7 @@ extern OOP _gst_make_pool_array (const c
/* This resolves the variable binding constant expressed by the LIST parse
tree node. Unless DECLARE_TEMPORARY is false, temporary variables
may be automatically declared. */
-extern tree_node _gst_find_variable_binding (tree_node list,
- mst_Boolean declare_temporary)
+extern tree_node _gst_find_variable_binding (tree_node list)
ATTRIBUTE_HIDDEN;
/* This returns the dictionary in which to define an undeclared variable
--- orig/libgst/tree.c
+++ mod/libgst/tree.c
@@ -342,13 +342,13 @@ _gst_make_string_constant (YYLTYPE *loca
tree_node
_gst_make_deferred_binding_constant (YYLTYPE *location,
- OOP keyOOP)
+ tree_node varNode)
{
tree_node result;
result = make_tree_node (location, TREE_CONST_EXPR);
result->v_const.constType = CONST_DEFERRED_BINDING;
- result->v_const.val.oopVal = keyOOP;
+ result->v_const.val.aVal = varNode;
return (result);
}
@@ -760,6 +760,16 @@ print_const_node (tree_node node,
_gst_print_tree (node->v_const.val.aVal, level + 7);
break;
+ case CONST_DEFERRED_BINDING:
+ printf ("deferred variable binding: ");
+ _gst_print_tree (node->v_const.val.aVal, level + 27);
+ break;
+
+ case CONST_BINDING:
+ printf ("variable binding: ");
+ _gst_print_tree (node->v_const.val.aVal, level + 18);
+ break;
+
default:
_gst_errorf ("Unknown constant type %d", node->v_const.constType);
}
--- orig/libgst/tree.h
+++ mod/libgst/tree.h
@@ -336,9 +336,9 @@ extern tree_node _gst_make_string_consta
ATTRIBUTE_HIDDEN;
/* Create a const_node storing a deferred variable binding, whose key
- is the symbol KEYOOP. */
+ is the variable VARNODE. */
extern tree_node _gst_make_deferred_binding_constant (YYLTYPE *location,
- OOP keyOOP)
+ tree_node varNode)
ATTRIBUTE_HIDDEN;
/* Create a const_node for an array whose elements are
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Help-smalltalk] [PATCH] Deferred variable bindings, part 3/3,
Paolo Bonzini <=