29. Thực thi dựa trên ngăn xếp

CPython thực thi hầu hết mã byte bằng máy xếp chồng. Máy ngăn xếp sử dụng ngăn xếp toán hạng ngầm thay vì đặt tên rõ ràng cho các thanh ghi nguồn và đích trong mỗi lệnh.

Trong CPython, ngăn xếp này thuộc về khung hiện tại. Nó lưu trữ các tham chiếu đến các đối tượng Python. Hướng dẫn mã byte đẩy đối tượng, bật đối tượng, kiểm tra đối tượng, thay thế đối tượng và sử dụng đối tượng để tính toán kết quả mới.

Một biểu thức đơn giản:python id="kz6m7x" x = a + b được thực hiện về mặt khái niệm như:text id="eurdpx" LOAD_FAST a push a LOAD_FAST b push b BINARY_OP + pop b and a, push result STORE_FAST x pop result into local x Luồng hướng dẫn không nói:text id="ardj57" add local_a, local_b, local_x Thay vào đó, nó nói:```text id="jzzlmf" load a load b add top two stack values store result


## 29.1 Tại sao CPython sử dụng máy xếp chồng

Máy ngăn xếp cung cp cho mã byte mt biu din nh gn. Nhiu lnh không cn v trí toán hng rõ ràng vì chúng hot động trên đỉnh ngăn xếp.

Ví d:```python id="e4954y"
return (a + b) * c
```có th được biu din dưới dng:```text id="nppt1h"
LOAD_FAST a
LOAD_FAST b
BINARY_OP +
LOAD_FAST c
BINARY_OP *
RETURN_VALUE
```các`BINARY_OP`lnh không cn đặt tên cho các thanh ghi đầu vào ca nó. Nó luôn ly toán hng t ngăn xếp.

Điu này gi cho mã byte đơn gin:```text id="pr4b42"
instructions are small
operands are usually indexes or small integers
temporary values do not need names
compiler stack-depth analysis is straightforward
interpreter execution model is uniform
```Máy đăng ký s mã hóa các v trí toán hng rõ ràng hơn:```text id="ugbzwm"
r3 = add r1, r2
r4 = mul r3, r0
return r4
```Điu đó có th làm gim s lượng lnh trong mt s thiết kế, nhưng nó yêu cu định dng mã byte khác và chiến lược biên dch khác. CPython trước đây đã s dng mô hình hướng ngăn xếp.

## 29.2 Ngăn xếp giá trị khung

Mi khung thc thi có b lưu tr cho các giá tr tm thi.

V mt khái nim:```text id="ia1aa5"
frame
    fast locals
    cell variables
    free variables
    value stack
```Vì:```python id="39cqdr"
def f(a, b):
    return a + b
```khung có th được hiu là:```text id="mq1wny"
localsplus
    [0] a
    [1] b
    [2...] value stack
```Trong quá trình thc hin:```text id="oq18jh"
LOAD_FAST a
    stack: [a]

LOAD_FAST b
    stack: [a, b]

BINARY_OP +
    stack: [a_plus_b]

RETURN_VALUE
    stack: []
    return a_plus_b
```Các ca hàng ngăn xếp`PyObject *`tài liu tham kho. Nó không lưu tr các s nguyên C không được đóng hp, các s nguyên gp đôi hoc các t máy biu th các giá tr Python trong vic thc thi mã byte thông thường.

Vì`a = 2`Và`b = 3`, ngăn xếp cha các con tr ti các đối tượng s nguyên Python.```text id="4h720d"
stack slot 0 -> PyLongObject(2)
stack slot 1 -> PyLongObject(3)
```## 29.3 Con trỏ ngăn xếp

Trình thông dch duy trì mt con tr ngăn xếp cho khung hin ti.

V mt khái nim:```c id="l1xymk"
PyObject **stack_pointer;
```Mt cú đẩy ghi mt giá tr vào khe ngăn xếp hin ti và nâng cao con tr.```c id="0gozoa"
*stack_pointer = value;
stack_pointer++;
```Mt ca s bt lên di chuyn con tr tr li và đọc giá tr.```c id="xj0vaq"
stack_pointer--;
value = *stack_pointer;
```Vic trin khai CPython thc s s dng macro, b nh chuyên dng, quy ước v quyn s hu tham chiếu và mã hướng dn được to. Nhưng hot động ct lõi vn là đẩy và bt.

Mt du vết ngăn xếp đơn gin:```text id="9taxcy"
initial:
    sp -> slot 0

push a:
    slot 0 = a
    sp -> slot 1

push b:
    slot 0 = a
    slot 1 = b
    sp -> slot 2

pop:
    sp -> slot 1
    value = slot 1
```Con tr ngăn xếp đánh du v trí ngăn xếp trng tiếp theo.

## 29.4 Hiệu ứng ngăn xếp

Mi lnh đều có hiu ng ngăn xếp.

Hiu ng ngăn xếp cho biết lnh thay đổi chiu cao ngăn xếp như thế nào.

| Hướng dn | Pops | Đẩy | Hiu ng ròng |
|---|---:|---:|---:|
|`LOAD_CONST`| 0 | 1 |`+1` |
| `LOAD_FAST`| 0 | 1 |`+1` |
| `STORE_FAST`| 1 | 0 |`-1` |
| `POP_TOP`| 1 | 0 |`-1` |
| `BINARY_OP`| 2 | 1 |`-1` |
| `RETURN_VALUE`| 1 | 0 | thoát khi khung |
|`CALL`| có th gi và lp lun | kết qu | biến |
|`BUILD_LIST`| N | 1 |`1 - N`|

Trình biên dch s dng hiu ng ngăn xếp để tính toán kích thước ngăn xếp ti đa mà mt đối tượng mã cn.

Giá tr đó được lưu tr trong đối tượng mã dưới dng`co_stacksize`.

```python id="e077y8"
def f(a, b, c):
    return (a + b) * c

print(f.__code__.co_stacksize)

co_stacksizecho CPython biết mã này có thể yêu cầu bao nhiêu dung lượng ngăn xếp tạm thời trong quá trình thực thi.

29.5 Đánh giá một biểu thức nhị phân

Hãy xem xét:```python id="xjqe7p" def f(a, b, c): return a + b * c


Vic thc thi ngăn xếp khái nim là:```text id="0lb9i7"
LOAD_FAST a
LOAD_FAST b
LOAD_FAST c
BINARY_OP *
BINARY_OP +
RETURN_VALUE
```Tng bước mt:

| Bước | Hướng dn | Xếp chng trước | Xếp chng sau |
|---:|---|---|---|
| 1 |`LOAD_FAST a` | `[]` | `[a]`|
| 2 |`LOAD_FAST b` | `[a]` | `[a, b]`|
| 3 |`LOAD_FAST c` | `[a, b]` | `[a, b, c]`|
| 4 |`BINARY_OP *` | `[a, b, c]` | `[a, b*c]`|
| 5 |`BINARY_OP +` | `[a, b*c]` | `[a + b*c]`|
| 6 |`RETURN_VALUE` | `[result]`| tr li |

Trình biên dch chn th t lnh duy trì ng nghĩa biu thc Python trong khi s dng ngăn xếp.

## 29.6 Dấu ngoặc đơn và thứ tự ngăn xếp

Du ngoc đơn thay đổi th t đánh giá.```python id="g8ade6"
def f(a, b, c):
    return (a + b) * c
```Mã byte khái nim:```text id="1fshyd"
LOAD_FAST a
LOAD_FAST b
BINARY_OP +
LOAD_FAST c
BINARY_OP *
RETURN_VALUE
```Tng bước mt:

| Bước | Hướng dn | Xếp chng sau |
|---:|---|---|
| 1 |`LOAD_FAST a` | `[a]`|
| 2 |`LOAD_FAST b` | `[a, b]`|
| 3 |`BINARY_OP +` | `[a+b]`|
| 4 |`LOAD_FAST c` | `[a+b, c]`|
| 5 |`BINARY_OP *` | `[(a+b)*c]`|
| 6 |`RETURN_VALUE`| tr li |

Máy ngăn xếp biu din các biu thc lng nhau mt cách t nhiên bng cách đánh giá các biu thc con và để li kết qu ca chúng trên ngăn xếp.

## 29.7 Thứ tự toán hạng

Đối vi các phép toán nh phân, th t toán hng rt quan trng.

Vì:```python id="dm51wp"
left - right
```trình thông dch phi gi phép tr vi toán hng trái và phi chính xác.

Ngăn xếp trước`BINARY_OP -`là:```text id="ghn1ei"
[left, right]
```Thao tác s bt toán hng bên phi trước, sau đó đến toán hng bên trái:```c id="8cs8ys"
right = pop();
left = pop();
result = subtract(left, right);
push(result);
```Nếu th t b đảo ngược, phép tr, chia, so sánh và nhiu thao tác do người dùng xác định s sai.

Vn đề tương t xut hin trong các cuc gi, lp ch mc, cài đặt thuc tính và gii nén.

## 29.8 Bài tập tiêu thụ các giá trị ngăn xếp

Bài tp s dng các giá tr ngăn xếp được to bi các biu thc.```python id="dk9je6"
x = a + b
```Thc hin khái nim:```text id="nw82k0"
LOAD_FAST a       stack: [a]
LOAD_FAST b       stack: [a, b]
BINARY_OP +       stack: [result]
STORE_FAST x      stack: []

STORE_FASTtiêu thụ giá trị ngăn xếp trên cùng và lưu trữ nó vào một vị trí cục bộ.

Đối với nhiều nhiệm vụ:```python id="7bq1ez" x = y = value


Về mặt khái niệm:```text id="tc6ix1"
LOAD_FAST value
COPY
STORE_FAST x
STORE_FAST y
```Mã byte chính xác thay đổi tùy theo phiên bản Python, nhưng nguyên tắc ngăn xếp giống nhau: mục tiêu gán sử dụng các giá trị từ ngăn xếp.

## 29.9 Lệnh gọi hàm trên ngăn xếp

Các cuộc gọi hàm sử dụng ngăn xếp để sắp xếp các đối số có thể gọi được.

Vì:```python id="zluswf"
result = f(a, b)
```ngăn xếp phải chứa đối số có thể gọi được và các đối số theo bố cục mà lệnh gọi mong đợi.

Về mặt khái niệm:```text id="yvk6nb"
LOAD_FAST f       stack: [f]
LOAD_FAST a       stack: [f, a]
LOAD_FAST b       stack: [f, a, b]
CALL 2            stack: [result]
STORE_FAST result stack: []
```Lệnh gọi biết số lượng đối số vị trí. Nó sử dụng đối số và có thể gọi được, gọi bộ máy gọi và đẩy giá trị trả về.

Các lệnh gọi hàm phức tạp hơn khi chúng bao gồm:```text id="wi0q0p"
keyword arguments
default values
starred arguments
double-starred mappings
bound methods
callable classes
C functions
Python functions
coroutines
```Nhưng ngăn xếp đánh giá vẫn mang các toán hạng gọi ngay lập tức.

## 29.10 Cuộc gọi phương thức

Các cuộc gọi phương thức được tối ưu hóa vì chúng phổ biến.

Vì:```python id="4dpcx3"
obj.method(arg)
```mô hình ngây thơ là:```text id="bxncuk"
load obj
load attribute method
create bound method object
load arg
call bound method
```Việc tạo một đối tượng phương thức ràng buộc cho mỗi cuộc gọi có thể tốn kém.

CPython sử dụng mã byte gọi phương thức chuyên dụng và đường dẫn cuộc gọi để tránh các đối tượng tạm thời không cần thiết khi có thể.

Về mặt khái niệm, đường dẫn được tối ưu hóa cố gắng thể hiện:```text id="2vrzhp"
call underlying function with self and args
```thay vì:```text id="a30j23"
create bound method object
then call it
```Do đó, bố cục ngăn xếp cho các lệnh gọi phương thức có thể khác với các lệnh gọi hàm đơn giản về chi tiết triển khai. Mục tiêu vẫn giữ nguyên: sắp xếp trạng thái và đối số có thể gọi được để bộ máy gọi có thể chạy hiệu quả.

## 29.11 Truy cập thuộc tính và giá trị ngăn xếp

Truy cập thuộc tính sử dụng một đối tượng và tạo ra một giá trị thuộc tính.```python id="yr0lx4"
value = obj.name
```Về mặt khái niệm:```text id="k5xpeh"
LOAD_FAST obj       stack: [obj]
LOAD_ATTR name      stack: [value]
STORE_FAST value    stack: []

LOAD_ATTRbật hoặc đọc đối tượng, thực hiện tra cứu thuộc tính và đưa ra kết quả.

Tra cứu thuộc tính có thể liên quan đến:text id="mh8xew" type lookup descriptor protocol instance dictionary lookup slots properties custom __getattribute__ custom __getattr__ inline cache checks Từ quan điểm của máy xếp chồng, thao tác rất đơn giản:```text id="x0kf3f" object in attribute value out


## 29.12 Đăng ký và lập chỉ mục

Đăng ký cũng s dng ngăn xếp.```python id="rey7pr"
value = xs[i]
```Thc hin khái nim:```text id="r32lp4"
LOAD_FAST xs       stack: [xs]
LOAD_FAST i        stack: [xs, i]
BINARY_SUBSCR      stack: [value]
STORE_FAST value   stack: []
```Đối vi nhim v:```python id="enkjpe"
xs[i] = value
```ngăn xếp phi cha vùng cha, ch mc và giá tr được gán.

V mt khái nim:```text id="8q3nbv"
LOAD_FAST value    stack: [value]
LOAD_FAST xs       stack: [value, xs]
LOAD_FAST i        stack: [value, xs, i]
STORE_SUBSCR       stack: []
```Th t chính xác được chn như vy`STORE_SUBSCR`có th bt toán hng mt cách nht quán.

## 29.13 Container xây dựng

Danh sách, b d liu, tp hp và ký t chính t s dng ngăn xếp.```python id="8qazhy"
xs = [a, b, c]
```V mt khái nim:```text id="q3tfjh"
LOAD_FAST a
LOAD_FAST b
LOAD_FAST c
BUILD_LIST 3
STORE_FAST xs
```S phát trin ca ngăn xếp:

| Hướng dn | Xếp chng sau |
|---|---|
|`LOAD_FAST a` | `[a]` |
| `LOAD_FAST b` | `[a, b]` |
| `LOAD_FAST c` | `[a, b, c]` |
| `BUILD_LIST 3` | `[[a, b, c]]` |
| `STORE_FAST xs` | `[]` |

`BUILD_LIST 3`tiêu th ba giá tr ngăn xếp và đẩy mt đối tượng danh sách.

Đối vi t đin:```python id="u3ds6p"
d = {"a": x, "b": y}
```ngăn xếp có th cha các đối tượng khóa và giá tr trước khi lnh xây dng chính t s dng chúng.

## 29.14 Giải nén

Vic gii nén đảo ngược vic xây dng container.```python id="ooj3e0"
a, b = pair
```V mt khái nim:```text id="ro1rmt"
LOAD_FAST pair
UNPACK_SEQUENCE 2
STORE_FAST a
STORE_FAST b
```Lnh gii nén s dng mt ln lp và đẩy các phn t ca nó.

Trình biên dch phi sp xếp th t lưu tr sao cho các biến phù hp nhn được giá tr chính xác.

Vì:```python id="4wc70r"
a, b = [1, 2]
```ngăn xếp sau khi gii nén có th có khái nim:```text id="ajf8h4"
[1, 2]
```Sau đó các ca hàng tiêu th giá tr.

Gii nén lng nhau:```python id="mvd1oq"
a, (b, c) = value
```yêu cu nhiu thao tác gii nén và sp xếp ngăn xếp cn thn.

## 29.15 So sánh

Vic so sánh s dng toán hng và đẩy kết qu Boolean hoc kết qu so sánh khác.```python id="z499ha"
x < y
```V mt khái nim:```text id="58s9qc"
LOAD_FAST x
LOAD_FAST y
COMPARE_OP <
```ngăn xếp:```text id="8lxjax"
before COMPARE_OP: [x, y]
after COMPARE_OP:  [result]
```So sánh theo chui thì tinh tế hơn.```python id="97mjg8"
a < b < c
```Python đánh giá`b`ch mt ln và gi li cho ln so sánh th hai.

V mt khái nim:```text id="202tno"
load a
load b
compare a < b
if false, stop
keep b
load c
compare b < c
```Máy xếp chng phi sao chép hoc xoay các giá tr để tránh đánh giá`b`hai ln.

## 29.16 Đoản mạch Boolean

Biu thc Boolean s dng bước nhy và ngăn xếp.```python id="u61h0m"
a and b
```Nếu như`a`là sai, Python tr v`a`mà không đánh giá`b`.

V mt khái nim:```text id="j7lc2d"
LOAD_FAST a
if false, jump to end and keep a
POP_TOP
LOAD_FAST b
end:
```Vì:```python id="v0ux9n"
a or b
```Nếu như`a`đúng, Python tr v`a`mà không đánh giá`b`.

```text id="38razm"
LOAD_FAST a
if true, jump to end and keep a
POP_TOP
LOAD_FAST b
end:
```Ngăn xếp được s dng để bo toàn kết qu đã chn.

Điu này gii thích ti sao Python`and`Và`or`tr v mt trong các toán hng ca h, không nht thiết`True`hoc`False`.

```python id="n4qhf6"
result = [] or [1, 2]
```tr v:```text id="n0s1kg"
[1, 2]
```## 29.17 Biểu thức điều kiện

Mt biu thc có điu kin:```python id="77rz4v"
x if cond else y
```s dng các nhánh.

Mã byte khái nim:```text id="3epj6l"
LOAD_FAST cond
POP_JUMP_IF_FALSE else_branch

LOAD_FAST x
JUMP end

else_branch:
LOAD_FAST y

end:
```Ngăn xếp sau biu thc cha chính xác mt giá tr:`x`hoc`y`.

Đây là mt bt biến trình biên dch chính. Bt k nhánh nào thc thi, hình dng ngăn xếp ti đim hp nht phi tương thích.

## 29.18 Bất biến hình dạng ngăn xếp

Ti các đim hp nht lung điu khin, trình biên dch phi duy trì hình dng ngăn xếp nht quán.

Ví d:```python id="hq40fy"
if cond:
    x = a
else:
    x = b
```C hai nhánh phi ri khi ngăn xếp  trng thái tương thích trước khi lung điu khin tham gia li.

Đối vi các nhánh cp biu thc:```python id="25hx6g"
result = a if cond else b
```c hai nhánh phi để li mt giá tr trên ngăn xếp.```text id="6wovt1"
then branch leaves: [a]
else branch leaves: [b]
merge expects:      [one value]
```Nếu mt nhánh để li hai giá tr và mt nhánh khác để li mt giá tr, thì mã byte sau này s không biết phi tiêu th cái gì.

Do đó, tính đúng đắn ca ngăn xếp là trách nhim ca người biên dch cũng như trách nhim ca người phiên dch.

## 29.19 Vòng lặp và ngăn xếp

Vòng lp s dng bước nhy. Ngăn xếp phi được cân bng  ranh gii vòng lp.

Ví d:```python id="0n8atk"
while i < n:
    i += 1
```Thc hin khái nim:```text id="f8q5zf"
loop_start:
    LOAD_FAST i
    LOAD_FAST n
    COMPARE_OP <
    POP_JUMP_IF_FALSE loop_end

    LOAD_FAST i
    LOAD_CONST 1
    BINARY_OP +=
    STORE_FAST i

    JUMP loop_start

loop_end:
```Ti`loop_start`, ngăn xếp phi  dng mong đợi sau mi ln lp. Thông thường nó trng đối vi các vòng lp cp câu lnh.

Nếu thân vòng lp để li các giá tr ngăn xếp b sung thì ln lp tiếp theo s bt đầu b hng.

## 29,20 cho vòng lặp

A`for`vòng lp da trên giao thc iterator.```python id="n5tak3"
for x in xs:
    body(x)
```V mt khái nim:```text id="xowkx6"
LOAD_FAST xs
GET_ITER

loop:
    FOR_ITER end
    STORE_FAST x

    LOAD_FAST body
    LOAD_FAST x
    CALL 1
    POP_TOP

    JUMP loop

end:
```Trình lp vn còn trên ngăn xếp qua các ln lp vòng lp.

Chế độ xem ngăn xếp đơn gin hóa:```text id="hiog6p"
after GET_ITER:
    [iterator]

FOR_ITER success:
    [iterator, next_value]

STORE_FAST x:
    [iterator]

loop body runs:
    [iterator]

FOR_ITER exhausted:
    []
```Đây là trường hp quan trng trong đó mt giá tr được c ý gi nguyên trên ngăn xếp trên vùng lung điu khin.

## 29.21 Thử, Ngoại trừ và Kỷ luật xếp chồng

X lý ngoi l cũng ph thuc vào trng thái ngăn xếp.

Vì:```python id="ehr6ve"
try:
    risky()
except ValueError:
    recover()
```Người phiên dch phi biết:```text id="tf513e"
which bytecode range is protected
where the handler starts
what stack depth to restore on exception
what exception values to make available
```Khi mt ngoi l xy ra, CPython s chuyn sang trng thái ngăn xếp đã biết trước khi vào trình x lý.

Điu này là cn thiết vì ngoi l có th xy ra khi ngăn xếp cha các giá tr tm thi.

Ví d:```python id="mkevyx"
x = f(g(), h())
```Nếu như`h()`tăng lên, ngăn xếp có th đã cha`f`và kết qu ca`g()`. X lý ngoi l phi dn sch các phn tm thi này mt cách chính xác.

## 29.22 Khối cuối cùng

A`finally`khi phi chy trong quá trình tr v, lan truyn ngoi l,`break`, hoc`continue`.

```python id="jvfmzp"
def f():
    try:
        return 1
    finally:
        cleanup()
```Trình thông dch phi bo toàn kết qu tr v đang ch x lý trong khi thc hin vic dn dp.

V mt khái nim:```text id="9zb2u4"
prepare return value
enter finally
run cleanup
if cleanup succeeds:
    resume return
if cleanup raises:
    discard pending return and propagate new exception
```Trng thái ngăn xếp và khung phi th hin chính xác lung điu khin đang ch x lý này.`finally`không ch là mt chi nhánh. Đây là đim chn lung điu khin.

## 29.23 Với Tuyên bố

A`with`câu lnh biên dch thành các cuc gi đến`__enter__`Và`__exit__`.

```python id="swotvs"
with cm() as value:
    body(value)
```Hành vi khái nim:```text id="29ed2g"
manager = cm()
exit = manager.__exit__
value = manager.__enter__()
try:
    body(value)
finally:
    exit(...)
```Ngăn xếp được s dng để gi cho máy thoát khi trình qun lý bi cnh có sn cho đến khi khi thoát ra.

Điu này cho phép CPython gi chính xác`__exit__`để hoàn thành bình thường và hoàn thành ngoi l.

## 29,24 Giá trị ngăn xếp là tài liệu tham khảo

Mi khe ngăn xếp cha mt tham chiếu đến mt đối tượng Python.

Điu đó có nghĩa là các hot động ngăn xếp tương tác vi vic đếm tham chiếu.

Khi mt lnh đẩy mt đối tượng, nó phi đảm bo đối tượng đó vn còn tn ti.

Khi mt lnh xóa mt đối tượng khi ngăn xếp và không còn s hu nó na, nó phi gii phóng tham chiếu nếu thích hp.

Mt phép toán nh phân được đơn gin hóa:```c id="0lju6g"
right = pop();
left = pop();

result = PyNumber_Add(left, right);

Py_DECREF(left);
Py_DECREF(right);

if (result == NULL) {
    goto error;
}

push(result);
```Các quy tc s hu chính xác khác nhau tùy theo mã opcode và chc năng tr giúp. Nhưng tính bt biến là nghiêm ngt:```text id="2wi5o6"
objects on the stack must remain alive
objects removed from the stack must be released when no longer needed
```Li ngăn xếp có th dn đến rò r b nh, hết hn s dng, li hoc kết qu sai.

## 29.25 Tài liệu tham khảo được mượn và sở hữu

Hướng dn CPython thường phân bit các tham chiếu mượn vi các tham chiếu s hu.

Tham chiếu mượn có nghĩa là mã có th s dng đối tượng tm thi nhưng không s hu tham chiếu mi.

Mt tham chiếu được s hu có nghĩa là mã cui cùng phi gii phóng nó.

Các mc trong ngăn xếp thường cn được coi là tài liu tham kho thuc s hu hoc trc tiếp theo cách ngăn chn vic phân b sm.

Ví d: ti mt hng s t`co_consts`có th đọc mt tham chiếu mượn t b hng s, sau đó tăng s lượng tham chiếu ca nó trước khi đặt nó vào ngăn xếp.

V mt khái nim:```c id="83om3h"
value = code->consts[index];   /* borrowed */
Py_INCREF(value);              /* now owned */
push(value);
```Mt ln na, CPython hin đại có th s dng các macro được ti ưu hóa, nhưng quy tc trn đời vn được gi nguyên.

## 29.26 Thu gom rác và rác

Ngăn xếp giá tr là mt phn ca tp gc trc tiếp.

Nếu mt đối tượng nm trong ngăn xếp ca khung đang hot động thì đối tượng đó có th truy cp được và không được thu thp.

Ví d:```python id="mz56t7"
result = f(g(), h())
```Trong khi đánh giá cuc gi, các đối tượng trung gian có th ch tn ti trên ngăn xếp. Chúng có th chưa được lưu tr trong bt k biến cc b hoc vùng cha nào.

V mt khái nim:```text id="ioz8o6"
stack:
    f
    result_of_g
    result_of_h
```Nhng đối tượng đó đang hot động vì ngăn xếp khung tham chiếu đến chúng.

Khi khung b giãn do tr v hoc ngoi l, CPython s gii phóng các tham chiếu được gi trong ngăn xếp.

## 29.27 Ngăn xếp và truy nguyên

Nếu mt ngoi l xy ra, vic dn dp ngăn xếp phi din ra trước khi truy nguyên được hin th.

Ví d:```python id="2054au"
def f():
    return g(h())
```Nếu như`h()`tăng lên, lnh gi được đánh giá mt phn ti`g`phi b b rơi. Các giá tr tm thi trên ngăn xếp phi được gim đi.

Truy nguyên bo tn thông tin khung và hướng dn, nhưng không lưu gi các giá tr ngăn xếp tm thi chết tùy ý.

Đây là mt phn lý do ti sao mã x lý ngoi l trong trình thông dch li rt phc tp.

## 29.28 Thực thi và chuyên môn hóa dựa trên ngăn xếp

Chuyên môn hóa không loi b mô hình máy xếp chng.

Mt hot động chung:```text id="w24zf8"
BINARY_OP +
```có th tr thành mt phép toán chuyên bit để cng s nguyên, ni chui hoc trường hp ph biến khác.

Nhưng hp đồng ngăn xếp vn gi nguyên:```text id="5e8nnk"
input stack:  [left, right]
output stack: [result]
```Điu này rt quan trng. Chuyên môn hóa có th thay đổi đường dn nhanh ni b trong khi vn duy trì hành vi ngăn xếp cp mã byte.

Ví d:```text id="1cdxfe"
generic BINARY_OP
    pop left and right
    call generic numeric dispatch
    push result

specialized int add
    pop left and right
    verify both are exact ints
    perform fast int path
    push result
```Nếu các bin pháp bo v không thành công, trình thông dch có th quay tr li đường dn chung.

## 29,29 Bộ nhớ đệm nội tuyến và hiệu ứng ngăn xếp

B nh đệm ni tuyến lưu tr siêu d liu gn các hướng dn mã byte nhưng chúng không hot động ging như các giá tr ngăn xếp thông thường.

Vì:```text id="6a9ugx"
LOAD_ATTR name
CACHE
CACHE
```các mc trong b đệm có th chiếm không gian mã byte hoc siêu d liu trình thông dch, nhưng chúng không phi là các giá tr được đẩy lên ngăn xếp đánh giá Python.

Hiu ng ngăn xếp ca`LOAD_ATTR`còn li:```text id="08gvhh"
input:  [object]
output: [attribute_value]
```B đệm tăng tc quá trình chuyn đổi t đầu vào sang đầu ra.

S khác bit này rt quan trng khi đọc phn tháo g. Mt s mc được hin th có th đại din cho máy b nh đệm ca trình thông dch thay vì các hot động mà người dùng có th nhìn thy.

## 29.30 Ví dụ về độ sâu ngăn xếp

Hãy xem xét:```python id="w9gktu"
def f(a, b, c, d):
    return (a + b) * (c + d)
```Mã byte khái nim:```text id="2b4bdv"
LOAD_FAST a
LOAD_FAST b
BINARY_OP +
LOAD_FAST c
LOAD_FAST d
BINARY_OP +
BINARY_OP *
RETURN_VALUE
```S phát trin ca ngăn xếp:

| Bước | Hướng dn | Ngăn xếp |
|---:|---|---|
| 0 | bt đầu |`[]`|
| 1 |`LOAD_FAST a` | `[a]`|
| 2 |`LOAD_FAST b` | `[a, b]`|
| 3 |`BINARY_OP +` | `[a+b]`|
| 4 |`LOAD_FAST c` | `[a+b, c]`|
| 5 |`LOAD_FAST d` | `[a+b, c, d]`|
| 6 |`BINARY_OP +` | `[a+b, c+d]`|
| 7 |`BINARY_OP *` | `[(a+b)*(c+d)]`|
| 8 |`RETURN_VALUE`| tr li |

Độ sâu ngăn xếp ti đa là 3 trong chui khái nim này.

Trình biên dch tính toán điu này mt cách tĩnh.

## 29.31 Lệnh đánh giá

Python đã xác định th t đánh giá. Mã byte CPython phi bo toàn nó.

Đối vi các đối s gi hàm:```python id="mm75rh"
f(a(), b(), c())
```các cuc gi xy ra t trái sang phi.

V mt khái nim:```text id="1fhff2"
load f
call a()
push result of a
call b()
push result of b
call c()
push result of c
call f with three arguments
```Nếu như`b()`tăng,`c()`không được chy.

Máy ngăn xếp phi duy trì th t này đồng thi dn dp các giá tr tm thi khi có li.

## 29.32 Tác dụng phụ

Vì biu thc Python có th có tác dng ph nên vic thc thi ngăn xếp không th sp xếp li th t các thao tác mt cách tùy ý.

Ví d:```python id="1d9mjp"
items[i()] = value()
```Các cuc gi ti`i()`Và`value()`phi xy ra theo th t được ch định ca Python để đánh giá bài tp.

Mt ví d khác:```python id="hz0uwv"
f(x, x := 10)
```Các biu thc gán, lnh gi hàm, truy cp thuc tính và lp ch mc đều có th nh hưởng đến trng thái chương trình.

Trình biên dch phi phát ra mã byte tôn trng các tác dng ph này. Ngăn xếp ch là mt cơ chế thc thi ch không phi là giy phép để sp xếp li ng nghĩa.

## 29.33 Máy ngăn xếp so với ngăn xếp cuộc gọi Python

Ngăn xếp đánh giá và ngăn xếp lnh gi Python khác nhau.

Ngăn xếp đánh giá nm trong mt khung:```text id="xm2eri"
frame f
    value stack: temporary operands
```Ngăn xếp cuc gi Python là mt chui các khung:```text id="6gz9pq"
frame a
    calls frame b
        calls frame c
```Lnh gi hàm s to mt khung mi. Khung mi đó có ngăn xếp đánh giá riêng.

Ví d:```python id="hh6rmw"
def a():
    return b(1 + 2)

def b(x):
    return x * 10
```Trong lúc`a`, biu thc`1 + 2`công dng`a`ngăn xếp giá tr ca. Khi`b`được gi là,`b`có khung riêng và ngăn xếp giá tr riêng.

## 29.34 Máy xếp chồng so với C Stack

Ngăn xếp giá tr CPython cũng khác vi ngăn xếp C gc.

| Ngăn xếp | Ý nghĩa |
|---|---|
| Ngăn xếp giá tr Python | Toán hng đối tượng Python tm thi bên trong mt khung |
| Ngăn xếp cuc gi Python | Chui khung Python |
| Ngăn xếp C | Các khung lnh gi gc được trình thông dch và hàm C s dng |

Truy nguyên hin th ngăn xếp lnh gi Python ch không phi ngăn xếp C đầy đủ.

Ngăn xếp giá tr thường không hin th trong truy nguyên. Nó là mt cu trúc thc thi ni b thông dch viên.

## 29,35 Tham nhũng ngăn xếp

Trình thông dch da vào k lut ngăn xếp chính xác.

Nếu mt opcode hin th quá nhiu giá tr, không hin th đủ giá tr, đẩy sai s lượng giá tr hoc x lý sai đường dn li thì khung s tr nên không hp l.

Hu qu có th xy ra:```text id="lbfom7"
wrong Python result
crash
memory leak
use-after-free
invalid traceback
corrupted exception state
security-sensitive memory bug
```Đây là lý do ti sao các lnh mã byte CPython phi có hiu ng ngăn xếp được xác định rõ ràng và ti sao đầu ra ca trình biên dch phi nht quán.

Để phát trin ct lõi, vic kim tra hiu ng ngăn xếp không mang tính thm m. Đó là mt điu kin đúng đắn.

## 29.36 Tháo rời hành vi ngăn xếp

s dng`dis`nghiên cu thc thi ngăn xếp.```python id="ufy4lp"
import dis

def f(a, b, c):
    return (a + b) * c

dis.dis(f)
```Sau đó theo dõi ngăn xếp theo cách th công:```text id="e45wnw"
start: []
LOAD_FAST a       [a]
LOAD_FAST b       [a, b]
BINARY_OP +       [a+b]
LOAD_FAST c       [a+b, c]
BINARY_OP *       [(a+b)*c]
RETURN_VALUE      return
```Bài tp này hu ích vì nó kết ni mã ngun, mã byte và thc thi khung.

## 29.37 Một trình thông dịch ngăn xếp nhỏ

Trình thông dch ngăn xếp ti thiu cho s hc có th hin th mô hình.```python id="e126pg"
LOAD_CONST = "LOAD_CONST"
ADD = "ADD"
MUL = "MUL"
RETURN = "RETURN"

def run(code, consts):
    stack = []

    for op, arg in code:
        if op == LOAD_CONST:
            stack.append(consts[arg])

        elif op == ADD:
            right = stack.pop()
            left = stack.pop()
            stack.append(left + right)

        elif op == MUL:
            right = stack.pop()
            left = stack.pop()
            stack.append(left * right)

        elif op == RETURN:
            return stack.pop()

    raise RuntimeError("missing RETURN")
```Chy:```python id="57jzcg"
code = [
    (LOAD_CONST, 0),
    (LOAD_CONST, 1),
    (ADD, None),
    (LOAD_CONST, 2),
    (MUL, None),
    (RETURN, None),
]

consts = [2, 3, 4]

print(run(code, consts))
```Điu này tính toán:```text id="jwwxxd"
(2 + 3) * 4
```Mô hình này nh hơn nhiu so vi CPython, nhưng ý tưởng v ngăn xếp toán hng thì ging nhau.

## 29.38 Thêm người dân địa phương vào Trình thông dịch đồ chơi

Mt thông dch viên phong phú hơn mt chút có th h tr người dân địa phương.```python id="w8sn78"
LOAD_FAST = "LOAD_FAST"
STORE_FAST = "STORE_FAST"
LOAD_CONST = "LOAD_CONST"
ADD = "ADD"
RETURN = "RETURN"

def run(code, consts, locals_):
    stack = []

    for op, arg in code:
        if op == LOAD_FAST:
            stack.append(locals_[arg])

        elif op == STORE_FAST:
            locals_[arg] = stack.pop()

        elif op == LOAD_CONST:
            stack.append(consts[arg])

        elif op == ADD:
            right = stack.pop()
            left = stack.pop()
            stack.append(left + right)

        elif op == RETURN:
            return stack.pop()

    raise RuntimeError("missing RETURN")
```Vì:```python id="7k6vgh"
x = a + 1
return x
```mã byte có th là:```python id="iq1afx"
code = [
    (LOAD_FAST, "a"),
    (LOAD_CONST, 0),
    (ADD, None),
    (STORE_FAST, "x"),
    (LOAD_FAST, "x"),
    (RETURN, None),
]

print(run(code, [1], {"a": 41}))
```Điu này th hin mô hình tương t như các cc b nhanh cng vi ngăn xếp giá tr ca CPython, mc dù CPython s dng các ch mc và con tr đối tượng thay vì t đin Python trong đường dn nóng.

## 29.39 Mô hình ngăn xếp giải thích điều gì

Mô hình ngăn xếp gii thích nhiu hành vi ca CPython:```text id="to5h59"
why bytecode instructions are small
why expression evaluation has a natural order
why co_stacksize exists
why local variables can be slot-indexed
why disassembly can be manually simulated
why exception paths must clean temporary values
why function calls have careful stack layouts
why specialization must preserve stack effects
why compiler correctness depends on stack balance
```Khi bn có th theo dõi ngăn xếp cho mt hàm, mã byte CPython s tr nên d đọc hơn nhiu.

## 29.40 Những hiểu lầm thường gặp

| Hiu lm | Đúng mu |
|---|---|
| Ngăn xếp lưu tr s nguyên máy thô | Nó lưu tr các tham chiếu đến các đối tượng Python |
| Ngăn xếp giá tr ging như ngăn xếp cuc gi | Mi khung hình có ngăn xếp giá tr riêng |
| Hướng dn mã byte đặt tên tt c các toán hng | Nhiu toán hng được n trên ngăn xếp |
| Th t ngăn xếp không quan trng | Th t toán hng rt quan trng |
| Các nhánh có th để li hình dng ngăn xếp tùy ý | Đim hp nht yêu cu hình dng ngăn xếp tương thích |
| Chuyên môn hóa loi b mô hình ngăn xếp | Nó gi cùng mt hp đồng ngăn xếp |
|`co_stacksize`năng động | Nó được tính toán t các hiu ng ngăn xếp bytecode |
| Nhng người tm thi luôn sng trong các biến cc b | Nhiu người ch sng nh vào giá tr |

## 29.41 Chiến lược đọc

Để nghiên cu cách thc thi da trên ngăn xếp, hãy s dng các ví d nh.

Bt đầu vi:```python id="5xvmyd"
def f(a, b):
    return a + b
```Sau đó:```python id="l91624"
def g(a, b, c):
    return (a + b) * c
```Sau đó:```python id="0pq8z6"
def h(xs):
    total = 0
    for x in xs:
        total += x
    return total
```Đối vi mi chc năng:```python id="fl0izq"
import dis
dis.dis(function_name)
```Theo dõi:```text id="lfc0ha"
which instructions push
which instructions pop
where the stack is empty
where values remain across jumps
where calls consume arguments
where returns consume values
```Quá trình này xây dng mt mô hình tinh thn c th ca người phiên dch.

## 29.42 Tóm tắt chương

Vic thc thi mã byte ca CPython da trên ngăn xếp. Mi khung có mt ngăn xếp giá tr được s dng để tham chiếu đối tượng Python tm thi. Các lnh mã byte đẩy các giá tr vào ngăn xếp, s dng các giá tr t ngăn xếp và để li kết qu cho các lnh sau.

Mu thiết yếu là:```text id="ebvtmi"
load operands
operate on top of stack
push result
store, return, call, branch, or continue
```Mô hình này gii thích vic đánh giá biu thc, truy cp biến cc b, lnh gi, vòng lp, dn dp ngoi l, xây dng vùng cha, gii nén, chuyên môn hóa và phân tích ngăn xếp trình biên dch.

Máy xếp chng có hình dng đơn gin nhưng nó là trung tâm ca quá trình thc thi CPython. Vic hiu nó làm cho mã byte có th đọc được và làm cho vòng lp đánh giá tr nên c th.