changeset 113:b804a51037c7

final?
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Sat, 06 Feb 2021 17:18:46 +0900
parents 8f0ff6d552ed
children c5b8cf006038
files paper/chapter/05-perl.tex paper/final.pdf paper/master_paper.pdf paper/src/AtomicTImpl2.cbc paper/src/Phils2.cbc paper/src/useGene.cbc
diffstat 6 files changed, 88 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/paper/chapter/05-perl.tex	Sat Feb 06 16:43:12 2021 +0900
+++ b/paper/chapter/05-perl.tex	Sat Feb 06 17:18:46 2021 +0900
@@ -450,6 +450,57 @@
 Implが持つ変数として、AtomicTにintを具体的な型として与えた型を定義している。
 \lstinputlisting[label=src:PhilsImplG, caption=Implファイル内でのジェネリクスの型の決定]{src/PhilsImpl.h}
 
+\subsection{CodeGear定義内でのジェネリクスの型決定}
+型定義をヘッダファイルでする以外の方法として、 CodeGearで定義するケースもある。
+ソースコード\ref{src:useGene}に示す例では、 InterfaceであるAtomicTはint型が型決定される。
+実装のコンストラクタであるcreateAtomicTImplも、int型で型決定されている。
+\lstinputlisting[label=src:useGene, caption=GenericsのCodeGear内での型決定]{src/useGene.cbc}
+
+\subsection{ジェネリクスの型決定手法}
+確認したように、ジェネリクスは型変数の定義と型に具体的な値をいれる2種類の使い方がある。
+ジェネリクスを導入する場合、これらのどちらの文脈で使われているかをPerlトランスパイラ側で判定する必要がある。
+
+これにはInterfaceのパーサーで取得できる、型変数のリスト情報を使用する。
+ジェネリクスは\texttt{<>}記号の中に型変数、もしくは具体的な型をいれる。
+解析しているファイルに登場する\texttt{<>}の中の文字列が、型変数として登録されていた場合は、そのソースコードは具体的な型をいれていない型定義ファイルであると捉える。
+逆に型変数情報になかった場合は具体的な型が決定された状況である。
+この場合は、どのDataGearであるかと、どの型に決定されたかを記憶する。
+
+\subsection{ジェネリクスの型生成}
+ジェネリクスに代入された具体的な型が決定した後は、ジェネリクスの型をそれぞれの具体的な型に合わせて変形させる必要がある。
+これはGearsOSはCbC上に実装されているが、CbCは型変数や、ジェネリクスの\texttt{<>}の様な構文をサポートしていない為である。
+つまり、ジェネリクスで拡張された構文を、等価なCbCのソースコードに書き換える必要がある。
+
+GearsOSでは次のアルゴリズムで型を変形する。
+\begin{itemize}
+  \item Interfaceの名前の末尾に\texttt{\_具体的な型}を与える
+  \begin{itemize}
+    \item AtomicT Interfaceにintを与えた場合、 AtomicT\_int
+  \end{itemize}
+  \item Implの名前の末尾に\texttt{\_具体的な型}を与える
+  \begin{itemize}
+    \item AtomicTImpl の場合intを与えた場合、 AtomicT\_intImpl\_int
+  \end{itemize}
+\end{itemize}
+
+この操作はすべてのCbCファイルについて操作する必要があるため、generate\_context.pl内で行われる。
+すべてのCbCファイル、ヘッダファイルについて調査を行い、型変数と具体的な型の組を作製する。
+
+CodeGearとDataGearによって、型決定後のオペレーションが異なる。
+DataGearの場合はcontext.hに書き込むunion Data型で計算で使うすべての型が決定する。
+そのため、union Data型を作製するDataGearの集合から、型変数を持つ型を削除し、代わりに具体的な型をあてはめた型をいれる。
+これによって、ジェネリクスで確定した型がcontext.hに書き込まれるようになる。
+
+CodeGearの場合は、変換した.cファイルを再度開き、使用されているジェネリクスの記述を置換する。
+置換自体は上記のアルゴリズムに沿って行われ、型変数の宣言に使われる\texttt{<>}記法は削除される。
+
+型変数を持つInterface/Implのコンストラクタが含まれるファイルは、対応する具体的な型の分コードを生成する。
+関数名も置換されるため衝突は発生しない。
+実際に変換したコードをソースコード\ref{src:Phils2}に示す。
+この例では、AtomicTにintを具体的な型として与えていた為、AtomicT\_int型が生成されている。
+
+\lstinputlisting[label=src:Phils2, caption=AtomicTの型をジェネリクスによってAtomicT\_intに置換した例]{src/Phils2.cbc}
+
 
 \section{generate\_stub.plのデバッグ機能の追加}\label{sec:generateStubDebug}
 変換されたGearsOSのコードが意図しない結果になっていた場合、 generate\_stub.plのデバッグをする必要がある。
Binary file paper/final.pdf has changed
Binary file paper/master_paper.pdf has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/paper/src/AtomicTImpl2.cbc	Sat Feb 06 17:18:46 2021 +0900
@@ -0,0 +1,20 @@
+AtomicT_int* createAtomicT_intImpl_int(struct Context* context,int init) {
+    struct AtomicT_int* atomicT_int  = &ALLOCATE(context, AtomicT_int)->AtomicT_int;
+    struct AtomicT_intImpl_int* atomic_t_impl = &ALLOCATE(context, AtomicT_intImpl_int)->AtomicT_intImpl_int;
+    atomicT_int->atomicT_int = (union Data*)atomic_t_impl;
+    atomicT_int->checkAndSet = C_checkAndSet_AtomicT_intImpl;
+    atomicT_int->set = C_set_AtomicT_intImpl;
+    atomic_t_impl->atomic = init;
+    atomic_t_impl->init = init;
+    return atomicT_int;
+
+}
+
+__code checkAndSet_AtomicT_intImpl(struct Context *context,struct AtomicT_intImpl_int* atomicT_int, int oldData, int newData, enum Code next, enum Code fail) {
+    if (__sync_bool_compare_and_swap(&atomicT_int->atomic, oldData, newData)) {
+        goto meta(context, next);
+    }
+    goto meta(context, fail);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/paper/src/Phils2.cbc	Sat Feb 06 17:18:46 2021 +0900
@@ -0,0 +1,7 @@
+__code putdown_rforkPhilsImpl(struct Context *context,struct PhilsImpl* phils, enum Code next) {
+    struct AtomicT_int* right_fork = phils->Rightfork;
+    Gearef(context, AtomicT_int)->atomicT_int = (union Data*) right_fork;
+    Gearef(context, AtomicT_int)->newData = -1;
+    Gearef(context, AtomicT_int)->next = C_putdown_lforkPhilsImpl;
+    goto meta(context, right_fork->set);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/paper/src/useGene.cbc	Sat Feb 06 17:18:46 2021 +0900
@@ -0,0 +1,10 @@
+__code createTask1(struct LoopCounter* loopCounter, struct TaskManager* taskManager) {
+    AtomicT<int>* fork0 = createAtomicTImpl<int>(contex,-1); // model checking : fork0
+    AtomicT<int>* fork1 = createAtomicTImpl<int>(contex,-1); // model checking : fork1
+    AtomicT<int>* fork2 = createAtomicTImpl<int>(contex,-1); // model checking : fork2
+    AtomicT<int>* fork3 = createAtomicTImpl<int>(contex,-1); // model checking : fork3
+    AtomicT<int>* fork4 = createAtomicTImpl<int>(contex,-1); // model checking : fork4
+
+    Phils* phils0 = createPhilsImpl(context,0,fork0,fork1); // model checking : phils0
+    Phils* phils1 = createPhilsImpl(context,1,fork1,fork2); // model checking : phils1
+...