กลับไปหน้าบทความ

อ่าน 3 นาที

ตัวชี้ที่ติดแท็ก

ในวิทยาการคอมพิวเตอร์ตัวชี้แบบแท็ก ( tagged pointer ) คือตัวชี้ (โดยเฉพาะ ที่อยู่หน่วยความจำ ) ที่มีข้อมูลเพิ่มเติมเชื่อมโยงอยู่ด้วย...

ตัวชี้ที่ติดแท็ก

ในวิทยาการคอมพิวเตอร์ตัวชี้แบบแท็ก ( tagged pointer ) คือตัวชี้ (โดยเฉพาะ ที่อยู่หน่วยความจำ ) ที่มีข้อมูลเพิ่มเติมเชื่อมโยงอยู่ด้วย เช่นบิตอ้างอิงหรือจำนวนการอ้างอิงข้อมูลเพิ่มเติมนี้มักจะถูก "รวม" เข้าไปในตัวชี้ หมายความว่าถูกจัดเก็บแบบอินไลน์ในข้อมูลที่แสดงที่อยู่ โดยใช้ประโยชน์จากคุณสมบัติบางอย่างของการกำหนดที่อยู่หน่วยความจำ ชื่อนี้มาจากระบบ " สถาปัตยกรรมแบบแท็ก " (tagged architecture) ซึ่งสงวนบิตไว้ในระดับฮาร์ดแวร์เพื่อระบุความสำคัญของแต่ละคำ ข้อมูลเพิ่มเติมนี้เรียกว่า "แท็ก" หรือ "แท็กต่างๆ" แม้ว่าในทางเทคนิคแล้ว "แท็ก" หมายถึงข้อมูลที่ระบุประเภทไม่ใช่ข้อมูลอื่นๆ แต่การใช้คำว่า "ตัวชี้แบบแท็ก" นั้นพบได้ทั่วไป

พับป้ายเข้าไปในตัวชี้

มีเทคนิคต่างๆ มากมายสำหรับการพับแท็กเข้าไปในตัวชี้[ 1 ]

สถาปัตยกรรมส่วนใหญ่สามารถระบุแอดเดรสได้ทีละไบต์ (หน่วยแอดเดรสที่เล็กที่สุดคือไบต์) แต่ข้อมูลบางประเภทมักจะจัดเรียงตามขนาดของข้อมูล ซึ่งมักจะเป็นเวิร์ด หรือพหุคูณของเวิร์ด ความไม่สอดคล้องกันนี้ทำให้ บิตที่สำคัญน้อยที่สุดบาง ส่วน ของตัวชี้ไม่ได้ถูกใช้งาน ซึ่งสามารถนำไปใช้เป็นแท็กได้ – ส่วนใหญ่มักเป็นฟิลด์บิต (แต่ละบิตเป็นแท็กแยกกัน) – ตราบใดที่โค้ดที่ใช้ตัวชี้จะทำการมาสก์บิตเหล่านี้ออกก่อนที่จะเข้าถึงหน่วยความจำ ตัวอย่างเช่น ใน สถาปัตยกรรม 32 บิต (ทั้งแอดเดรสและขนาดเวิร์ด) เวิร์ดมีขนาด 32 บิต = 4 ไบต์ ดังนั้นแอดเดรสที่จัดเรียงตามเวิร์ดจึงเป็นพหุคูณของ 4 เสมอ จึงลงท้ายด้วย 00 ทำให้เหลือ 2 บิตสุดท้ายที่ใช้งานได้ ในขณะที่ใน สถาปัตยกรรม 64 บิตเวิร์ดมีขนาด 64 บิต = 8 ไบต์ ดังนั้นแอดเดรสที่จัดเรียงตามเวิร์ดจึงลงท้ายด้วย 000 ทำให้เหลือ 3 บิตสุดท้ายที่ใช้งานได้ ในกรณีที่ข้อมูลถูกจัดเรียงตามพหุคูณของขนาดเวิร์ด บิตเพิ่มเติมก็จะสามารถใช้งานได้ ในกรณีของ สถาปัตยกรรม ที่สามารถระบุแอดเดรสตามคำได้ข้อมูลที่จัดเรียงตามคำจะไม่เหลือบิตว่างใดๆ เนื่องจากไม่มีความคลาดเคลื่อนระหว่างการจัดเรียงและการระบุแอดเดรส แต่ข้อมูลที่จัดเรียงตามขนาดที่เป็นพหุคูณของคำจะเหลือบิตว่าง

ในทางกลับกัน ในระบบปฏิบัติการบางระบบ ที่อยู่เสมือนจะแคบกว่าความกว้างของสถาปัตยกรรมโดยรวม ซึ่งทำให้บิตที่มีนัยสำคัญที่สุดเหลืออยู่สำหรับการติดแท็ก ซึ่งสามารถใช้ร่วมกับเทคนิคก่อนหน้านี้ในกรณีของที่อยู่ที่มีการจัดเรียงได้ โดยเฉพาะอย่างยิ่งในสถาปัตยกรรม 64 บิต เนื่องจากพื้นที่ที่อยู่ 64 บิตนั้นสูงกว่าความต้องการข้อมูลของแอปพลิเคชันส่วนใหญ่ ยกเว้นแอปพลิเคชันขนาดใหญ่ที่สุด ดังนั้นโปรเซสเซอร์ 64 บิตในทางปฏิบัติ จำนวนมาก จึงมีที่อยู่แคบกว่า โปรดทราบว่าความกว้างของที่อยู่เสมือนอาจแคบกว่า ความกว้าง ของที่อยู่ทางกายภาพซึ่งอาจแคบกว่าความกว้างของสถาปัตยกรรม สำหรับการติดแท็กตัวชี้ในพื้นที่ผู้ใช้พื้นที่ที่อยู่เสมือนที่ระบบปฏิบัติการจัดให้ (ซึ่งจัดให้โดยหน่วยจัดการหน่วยความจำ ) คือความกว้างที่เกี่ยวข้อง ในความเป็นจริง โปรเซสเซอร์บางตัวห้ามใช้ตัวชี้ที่ติดแท็กดังกล่าวในระดับโปรเซสเซอร์โดยเฉพาะ โดยเฉพาะอย่างยิ่งx86-64 ซึ่งกำหนดให้ ระบบปฏิบัติการ ต้องใช้ที่อยู่รูปแบบมาตรฐาน โดยที่บิตที่มีนัยสำคัญที่สุดเป็น 0 หรือ 1 ทั้งหมด

สุดท้ายนี้ ระบบ หน่วยความจำเสมือนในระบบปฏิบัติการ สมัยใหม่ส่วนใหญ่ จะสงวนบล็อกหน่วยความจำเชิงตรรกะรอบๆ ที่อยู่ 0 ไว้เป็นพื้นที่ใช้งานไม่ได้ ซึ่งหมายความว่า ตัวอย่างเช่น ตัวชี้ไปยัง 0 จะไม่ใช่ตัวชี้ที่ถูกต้อง และสามารถใช้เป็น ค่า ตัวชี้ว่าง พิเศษ ได้ ซึ่งแตกต่างจากเทคนิคที่กล่าวถึงก่อนหน้านี้ วิธีนี้อนุญาตให้ใช้ค่าตัวชี้พิเศษเพียงค่าเดียวเท่านั้น ไม่ใช่ข้อมูลเพิ่มเติมสำหรับตัวชี้โดยทั่วไป

ประวัติศาสตร์

หนึ่งในตัวอย่างแรกสุดของการสนับสนุนฮาร์ดแวร์สำหรับพอยเตอร์แบบแท็กในแพลตฟอร์มเชิงพาณิชย์คือIBM System/38 [ 2 ] ต่อมา IBM ได้เพิ่มการสนับสนุนพอยเตอร์แบบแท็กให้กับ สถาปัตยกรรม PowerPCเพื่อรองรับ ระบบปฏิบัติการ IBM iซึ่งเป็นวิวัฒนาการของแพลตฟอร์ม System/38 [ 3 ]

ตัวอย่างที่สำคัญของการใช้พอยเตอร์แบบแท็กคือ รันไทม์ Objective-CบนiOS 7บนARM64ซึ่งใช้ในiPhone 5Sใน iOS 7 ที่อยู่เสมือนจะมีข้อมูลที่อยู่เพียง 33 บิต แต่มีความยาว 64 บิต ทำให้เหลือ 31 บิตสำหรับแท็ก พอยเตอร์คลาส Objective-C จัดเรียงตาม 8 ไบต์ ทำให้มีพื้นที่ที่อยู่เพิ่มขึ้นอีก 3 บิต และฟิลด์แท็กถูกใช้เพื่อวัตถุประสงค์หลายอย่าง เช่น การจัดเก็บจำนวนการอ้างอิงและตรวจสอบว่าวัตถุมีตัวทำลาย หรือไม่ [ 4 ] [ 5 ]

macOS เวอร์ชันแรกๆ ใช้แอดเดรสแบบแท็กที่เรียกว่า Handles เพื่อเก็บการอ้างอิงไปยังอ็อบเจ็กต์ข้อมูล บิตสูงของแอดเดรสจะระบุว่าอ็อบเจ็กต์ข้อมูลนั้นถูกล็อก ล้างได้ และ/หรือมาจากไฟล์ทรัพยากร ตามลำดับ ซึ่งทำให้เกิดปัญหาความเข้ากันได้ เมื่อการกำหนดแอดเดรสของ macOS พัฒนาจาก 24 บิตเป็น 32 บิตใน System 7 [ 6 ]

ตัวชี้ว่างเทียบกับตัวชี้ที่จัดเรียงแล้ว

การใช้เลขศูนย์แทนพอยเตอร์ว่างนั้นพบได้บ่อยมาก โดยภาษาโปรแกรมหลายภาษา (เช่นAda ) อาศัยพฤติกรรมนี้อย่างชัดเจน ในทางทฤษฎีแล้ว ค่าอื่นๆ ในบล็อกหน่วยความจำเชิงตรรกะที่สงวนไว้โดยระบบปฏิบัติการสามารถใช้เพื่อระบุเงื่อนไขอื่นๆ นอกเหนือจากพอยเตอร์ว่างได้ แต่การใช้งานเหล่านี้ดูเหมือนจะหายาก อาจเป็นเพราะอย่างดีที่สุดก็ไม่สามารถพกพาได้โดยทั่วไปแล้ว ในการออกแบบซอฟต์แวร์เป็นที่ยอมรับกันว่า หากจำเป็นต้องใช้ค่าพอยเตอร์พิเศษที่แตกต่างจากค่าว่าง (เช่นเซนติเนลในโครงสร้างข้อมูล บางอย่าง ) โปรแกรมเมอร์ควรจัดเตรียมค่าดังกล่าวไว้อย่างชัดเจน

การใช้ประโยชน์จากการจัดเรียงของตัวชี้ให้ความยืดหยุ่นมากกว่าตัวชี้/ตัวบ่งชี้ว่างเปล่า เนื่องจากอนุญาตให้ติดแท็กข้อมูลให้กับตัวชี้ได้ เช่น ข้อมูลเกี่ยวกับประเภทของข้อมูลที่ชี้ไป เงื่อนไขในการเข้าถึง หรือข้อมูลอื่น ๆ ที่คล้ายกันเกี่ยวกับการใช้งานตัวชี้ ข้อมูลนี้สามารถให้มาพร้อมกับตัวชี้ที่ถูกต้องทุกตัวได้ ในทางตรงกันข้าม ตัวชี้/ตัวบ่งชี้ว่างเปล่าให้ค่าที่ติดแท็กได้เพียงจำนวนจำกัดเท่านั้น ซึ่งแตกต่างจากตัวชี้ที่ถูกต้อง

ในสถาปัตยกรรมแบบแท็ก (Tagged Architecture ) บิตจำนวนหนึ่งในทุกคำของหน่วยความจำจะถูกสงวนไว้เพื่อทำหน้าที่เป็นแท็ก สถาปัตยกรรมแบบแท็ก เช่นเครื่องลิสป์ (Lisp machines ) มักมีฮาร์ดแวร์ที่รองรับการตีความและประมวลผลพอยเตอร์แบบแท็ก

GNU libcmalloc()ให้ที่อยู่หน่วยความจำที่จัดเรียง 8 ไบต์สำหรับแพลตฟอร์ม 32 บิต และการจัดเรียง 16 ไบต์สำหรับแพลตฟอร์ม 64 บิต[ 7 ]สามารถรับค่าการจัดเรียงที่ใหญ่กว่าได้posix_memalign()ด้วย[ 8 ]

ตัวอย่าง

ตัวอย่างที่ 1

ในโค้ดภาษา C ต่อไปนี้ ค่าศูนย์ถูกใช้เพื่อระบุพอยเตอร์ว่าง:

void optionally_return_a_value ( int * optional_return_value_pointer ) { /* ... */ int value_to_return = 1 ;/* ไม่ใช่ค่า NULL ใช่หรือไม่? (โปรดทราบว่า NULL, ค่าตรรกะเท็จ และศูนย์ เปรียบเทียบกันได้เท่ากันในภาษา C) */ ถ้า( optional_return_value_pointer ) /* ถ้าใช่ ให้ใช้ตัวชี้ค่านี้เพื่อส่งค่าไปยังฟังก์ชันที่เรียก */ * optional_return_value_pointer = value_to_return ;/* มิฉะนั้น จะไม่สามารถอ้างอิงค่าที่ชี้โดยตัวชี้ได้ */ }

ตัวอย่างที่ 2

ในตัวอย่างนี้ โปรแกรมเมอร์ได้กำหนดตัวแปรส่วนกลางไว้ ซึ่งที่อยู่ของตัวแปรนั้นจะถูกใช้เป็นตัวบ่งชี้:

#define SENTINEL &sentinel_snode_t sentinel_s ;void do_something_to_a_node ( node_t * p ) { if ( NULL == p ) /* ทำบางอย่าง */ else if ( SENTINEL == p ) /* ทำอย่างอื่น */ else /* ถือว่า p เป็นตัวชี้ที่ถูกต้องไปยังโหนด */ }

ตัวอย่างที่ 3

สมมติว่าเรามีโครงสร้างข้อมูลtable_entryที่จัดเรียงให้ตรงกับขอบเขต 16 ไบต์เสมอ กล่าวคือ บิตที่มีค่าต่ำที่สุด 4 บิตของที่อยู่ของรายการในตารางจะเป็น 0 เสมอ(2⁴ = 16 )เรา สามารถใช้ 4 บิตนี้เพื่อระบุข้อมูลเพิ่มเติมให้กับรายการในตารางได้ ตัวอย่างเช่น บิต 0 อาจหมายถึงอ่านอย่างเดียว บิต 1 อาจหมายถึงมีการเปลี่ยนแปลง (รายการในตารางจำเป็นต้องได้รับการอัปเดต) เป็นต้น

ถ้าตัวชี้เป็นค่า 16 บิตแล้ว:

  • 0x3421เป็นตัวชี้แบบอ่านอย่างเดียวไปยังtable_entryที่อยู่ดังกล่าว0x3420
  • 0xf472เป็นตัวชี้ไปยังtable_entryที่อยู่ที่ ไม่ถูกต้อง0xf470

ข้อดี

ข้อดีหลักของพอยเตอร์ที่มีแท็กคือใช้พื้นที่น้อยกว่าพอยเตอร์ที่มีฟิลด์แท็กแยกต่างหาก ซึ่งอาจมีความสำคัญอย่างยิ่งเมื่อพอยเตอร์เป็นค่าส่งคืนจากฟังก์ชันนอกจากนี้ยังอาจมีความสำคัญในตารางพอยเตอร์ขนาดใหญ่ด้วย

ข้อดีที่ลึกซึ้งกว่านั้นคือ การจัดเก็บแท็กไว้ในตำแหน่งเดียวกับตัวชี้ ทำให้สามารถรับประกันความเป็นอะตอมิกของการดำเนินการที่อัปเดตทั้งตัวชี้และแท็กได้โดยไม่ต้องใช้ กลไก การซิงโครไนซ์ ภายนอก ซึ่งอาจเพิ่มประสิทธิภาพได้อย่างมาก โดยเฉพาะในระบบปฏิบัติการ

ข้อเสีย

พอยเตอร์แบบแท็กมีข้อจำกัดบางอย่างคล้ายกับลิสต์เชื่อมโยงแบบ XORแต่ในระดับที่น้อยกว่า ตัวอย่างเช่นดีบักเกอร์ บางตัว อาจไม่สามารถติดตามพอยเตอร์แบบแท็กได้อย่างถูกต้อง อย่างไรก็ตาม นี่ไม่ใช่ปัญหาสำหรับดีบักเกอร์ที่ออกแบบมาโดยคำนึงถึงพอยเตอร์แบบแท็กเป็นหลัก

การใช้เลขศูนย์แทนพอยเตอร์ว่างนั้นไม่มีข้อเสียดังกล่าว: มันแพร่หลาย ภาษาโปรแกรมส่วนใหญ่ถือว่าเลขศูนย์เป็นค่าว่างพิเศษ และได้รับการพิสูจน์แล้วว่ามีความแข็งแกร่ง ข้อยกเว้นคือวิธีที่เลขศูนย์มีส่วนร่วมในการแก้ไขการโอเวอร์โหลดใน C++ ซึ่งเลขศูนย์ถูกมองว่าเป็นจำนวนเต็มแทนที่จะเป็นพอยเตอร์ ด้วยเหตุนี้จึงนิยมใช้ค่าพิเศษnullptrมากกว่าเลขศูนย์ อย่างไรก็ตาม สำหรับพอยเตอร์แบบแท็ก มักจะไม่ใช้เลขศูนย์แทนพอยเตอร์ว่าง

ดึงข้อมูลมาจาก " https://en.wikipedia.org/w/index.php?title=Tagged_pointer&oldid=1354235821 "

สรุปเนื้อหา

ข้อมูลสำคัญจากบทความ

ข้อมูลสำคัญเกี่ยวกับ ตัวชี้ที่ติดแท็ก

ในวิทยาการคอมพิวเตอร์ตัวชี้แบบแท็ก ( tagged pointer ) คือตัวชี้ (โดยเฉพาะ ที่อยู่หน่วยความจำ ) ที่มีข้อมูลเพิ่มเติมเชื่อมโยงอยู่ด้วย...

พับป้ายเข้าไปในตัวชี้

มีเทคนิคต่างๆ มากมายสำหรับการพับแท็กเข้าไปในตัวชี้ [ 1 ]

ประวัติศาสตร์

หนึ่งในตัวอย่างแรกสุดของการสนับสนุนฮาร์ดแวร์สำหรับพอยเตอร์แบบแท็กในแพลตฟอร์มเชิงพาณิชย์คือ IBM System/38 [ 2 ] ต่อ มา IBM ได้เพิ่มการสนับสนุนพอยเตอร์แบบแท็กให้กับ สถาปัตยกรรม PowerPC เพื่อรองรับ ระบบปฏิบัติการ IBM i ซึ่งเป็นวิวัฒนาการของแพลตฟอร์ม System/38 [...

ตัวชี้ว่างเทียบกับตัวชี้ที่จัดเรียงแล้ว

การใช้เลขศูนย์แทนพอยเตอร์ว่างนั้นพบได้บ่อยมาก โดยภาษาโปรแกรมหลายภาษา (เช่น Ada ) อาศัยพฤติกรรมนี้อย่างชัดเจน ในทางทฤษฎีแล้ว ค่าอื่นๆ ในบล็อกหน่วยความจำเชิงตรรกะที่สงวนไว้โดยระบบปฏิบัติการสามารถใช้เพื่อระบุเงื่อนไขอื่นๆ นอกเหนือจากพอยเตอร์ว่างได้...