ソースを参照

Get rid of stack size optimization (made performance worse). Block-statement remembers its Scope.

Joeri Exelmans 5 年 前
コミット
4fb521b6f8
3 ファイル変更17 行追加17 行削除
  1. 8 14
      src/sccd/execution/memory.py
  2. 4 1
      src/sccd/syntax/scope.py
  3. 5 2
      src/sccd/syntax/statement.py

+ 8 - 14
src/sccd/execution/memory.py

@@ -21,10 +21,8 @@ class MemorySnapshot:
     self.temp_dirty = Bitmap() # positions in actual memory written to before flush_temp
     self.round_dirty = Bitmap() # positions in actual memory written to after flush_temp and before flush_round
 
-    self.stack_use = 0
-    self.stack = [None]*1024 # Storage for local scope values. Always temporary: no memory protocol applies to them
-
     self.scope = [memory.scope]
+    self.stack = [] # Storage for local scope values. Always temporary: no memory protocol applies to them
 
   def refresh(self):
     self.snapshot = list(self.actual)
@@ -47,18 +45,15 @@ class MemorySnapshot:
 
   def grow_stack(self, scope):
     self.scope.append(scope)
-    self.stack_use += scope.size()
-    if self.stack_use > len(self.stack):
-      self.stack.extend([None]*len(self.stack)) # double stack
+    self.stack.extend([None]*scope.localsize())
 
   def shrink_stack(self):
     scope = self.scope.pop()
-    self.stack_use -= scope.size()
-    if self.stack_use < len(self.stack) // 4 and len(self.stack) > 1024:
-      del self.stack[len(self.stack)//2:] # half stack
+    del self.stack[-scope.localsize():]
 
   def flush_temp(self):
-    assert self.stack_use == 0 # only allowed to be called in between statement executions or expression evaluations
+    assert len(self.stack) == 0 # only allowed to be called in between statement executions or expression evaluations
+    
     race_conditions = self.temp_dirty & self.round_dirty
     if race_conditions:
         raise Exception("Race condition for variables %s" % str(list(self.scope[-1].get_name(offset) for offset in race_conditions.items())))
@@ -67,9 +62,8 @@ class MemorySnapshot:
     self.temp_dirty = Bitmap() # reset
 
   def refresh(self):
-    assert self.stack_use == 0 # only allowed to be called in between statement executions or expression evaluations
-    # The following looks more efficient, but may be in fact slower in Python:
-    # for i in self.round_dirty.items():
-    #   self.snapshot[i] = self.actual[i] # refresh snapshot
+    assert len(self.stack) == 0 # only allowed to be called in between statement executions or expression evaluations
+
+    # Probably quickest to just copy the entire list in Python
     self.snapshot = list(self.actual) # refresh
     self.round_dirty = Bitmap() # reset

+ 4 - 1
src/sccd/syntax/scope.py

@@ -24,8 +24,11 @@ class Scope:
     self.names: Dict[str, Variable] = {}
     self.variables: List[str] = []
 
+  def localsize(self) -> int:
+    return len(self.variables)
+
   def size(self) -> int:
-    return self.start_offset + len(self.names)
+    return self.start_offset + len(self.variables)
 
   def all(self):
     if self.parent_scope:

+ 5 - 2
src/sccd/syntax/statement.py

@@ -60,15 +60,18 @@ class Assignment(Statement):
 @dataclass
 class Block(Statement):
     stmts: List[Statement]
+    scope: Optional[Scope] = None
 
     def init_stmt(self, scope):
-        local_scope = Scope("local", scope)
+        self.scope = Scope("local", scope)
         for stmt in self.stmts:
-            stmt.init_stmt(local_scope)
+            stmt.init_stmt(self.scope)
 
     def exec(self, current_state, events, memory):
+        memory.grow_stack(self.scope)
         for stmt in self.stmts:
             stmt.exec(current_state, events, memory)
+        memory.shrink_stack()
 
     def render(self) -> str:
         result = ""