Design: タグ付きGCポインタ

作成日 2016年12月17日  ·  41コメント  ·  ソース: WebAssembly/design

GCのドキュメントで、タグ付きポインタについての言及がないことに気づきまし

不透明な参照型の最初の提案の一部としても、タグを参照に関連付けることができる方法を公開すると便利です。

すべてのアーキテクチャまたはVM実装がこれを利用できるわけではなく、場合によってはボックス化する必要があることもあります。 タグに使用可能なスペースは、JSVMがそのタイプ情報を格納するためにすでに使用している場合もあります。 ただし、利用できる環境では、適切なアフォーダンスを用意しておくと非常に役立ちます。

これは、JavaScript列挙型の提案(TC39で調査することに興味があります)にも関連していると想像できます。 これは、この値のJavaScript表現である可能性があります。

managed objects

最も参考になるコメント

こんにちは@shriram 、私たちはC ++を超えて考えており、これらの機能を奇妙なものや重要でないものとは見なしていないので安心してください。 それらをサポートすることは、MVP後の議題にあります。 必ずしも一般的なcall / ccを追加する必要はないかもしれませんが、より限定された形式の区切られた継続はありそうにありません。 考えられる方向の1つは、代数効果ハンドラーです。構造化例外処理の提案はすでにあります。再開を追加することは、構造化形式の「スタックスイッチング」を提供し、言及したすべての制御抽象化を有効にするための「最も簡単な」方法です。 。

全てのコメント41件

これはすでにリニアメモリで実行できます。使用する前にポインタをマスクするだけです。 私はこのユースケースを検討するために何年も戦い続けており、サポートを利用することができ、計画があります。

@sebmarkbage列挙型提案の概要はありますか?

タグの場合:VMに「Nビットのタグが利用可能」というプロパティを与えて、それ以上のものを自分で処理するか、不特定の制限を超えた場合に自動的にサイドストレージを使用しますか?

@sebmarkbage 、可能性について考えています(ただし、おそらく主にタグ付きポインターではなく、オブジェクトヘッダー内のタグと、プレーン列挙型のタグ付き整数を意味します)。 ただし、VMとアーキテクチャが多様であるため、かなり注意が必要です。基本的に、Wasm型システムで合計と積の両方をプリミティブにする必要があります。 それがうまくいくかどうかは、現時点ではわかりません。

@jfbastien制御するのが良いのか、それともわかりません。場合によっては、タグ付きポインターよりもオブジェクトヘッダータグを使用する方が良いかもしれないと思います。 一般的に私は作者として管理するのが好きですが、この場合、ブランチごとに多くの追加コードを出荷する必要があるかもしれないので、自動的にサイドストレージを使用することに傾倒していると思います。

列挙型の提案をオンラインで見つけることができないようです。 これは値型の一部でしたが、値型から切り離して実行できると思います。 cc @littledan

@ rossberg-chromium私はタグ付きポインターを意味していましたが、あなたがそれについて言及したので、オブジェクトヘッダーのタグがV8のようないくつかのデザインでどのように役立つかがわかります。 プラットフォームに応じてどちらかを選択すると便利であることがわかりました。 確かにトリッキー。

@ rossberg-chromium今後、「私たちが考えている」のように「私たち」という言葉を使うときは、具体的に教えてください。 私の知る限り、この問題についての考えはこのコミュニティグループによって議論されておらず、このコミュニティグループの作業が誤って伝えられることを望んでいません。 たとえば、将来的にこれを「v8チーム」と表現したり、メンバーシップを与えるサブグループの名前を作成したりすることができます。 議長が、メンバーに情報を提供し、管理することなく、このグループの作業の方向性を推進する私的な談話の継続を許可した場合、議長を返還してください。 メンバーによって選出されていない議長がいる場合は、議長を返してください。

値型または型付きオブジェクトから切り離された方法でタグ付きポインターを追求することをお勧めします。 たとえば、ここでは2〜4タグビットに制限したい場合がありますが、JavaScriptに追加されたADTはそのような制限を表面化するべきではありません。 cc @tschneidereit

@ rossberg-chromiumが「私たち」について話すとき、彼はWASMに取り組んでいる人々の間で非公式な設定を意味します。 私が彼から3メートル離れて座っていることを考えると、このコミュニケーションを祝福するために特定のサブグループを確立することは多くのオーバーヘッドのようです:-)

タグ付けは合計型ほど一般的ではないと思います。 残念ながら、タグ付けは、基盤となるマシンのワード幅(ビット単位)にも関係しています。 ただし、無制限の合計型は、値の表現を完全にエンジンに任せます。これは、一部の言語実装者にとっては不快な場合があります。 したがって、制限された合計(たとえば、プリミティブ型と参照の一部のサブセットのみ)は、エンジンをそれほど複雑にすることなく、効率的な値の表現につながる可能性があります。

@titzer偶然にも、「私たち」(@ lars-t-hansen、私、その他のwasmの人々)は、常にタグ付き単語の表現を許可する、ある種の制限された合計の同じ基本的な考え方について話し合っていました。

この夏の会話から抜け出したのは、gc可能オブジェクト(おそらくTypedObjects)の個別のヒープがある設計では、2つの新しいwasmタイプが存在する可能性があるという考えでした。

「ポインタ」は、gc可能ヒープ内のいくつかのgcされたものへの不透明な参照(おそらくnull)です。 Wasm-32では4バイト、Wasm-64では8バイトです。

「ボックス」はポインタサイズのトリプルです。

  • ポインタ指定ビット(1ビット)
  • タグビット(2ビットまたは3ビット、ワードサイズに依存する可能性があります)
  • 値(ポインター指定子が設定されている場合はポインター、それ以外の場合は整数)

いくつかのもっともらしい操作:
boxptr(pointer、tag)-> Box [1、tag、pointer]
boxval(integer、tag)-> Box [0、tag、integer&〜15]
ptrbitof(Box)-> 0または1
tagof(ボックス)->タグ
ptrof(Box)->ポインタまたはボックスがポインタボックスでない場合はnull
valof(Box)->整数値またはボックスが整数ボックスでない場合は0

wasmのローカル変数とグローバル変数は、現在の型に加えて、ボックス型またはptr型になります。 ポインタとボックスは、線形ヒープに格納できません。

私がスケッチしたものは、少なくとも多くの動的言語にとって適切でパフォーマンスが高いはずです。 実際には、通常は3タグビット(ポインタビットと2ビット)で問題ありません。その後、追加のタグビットをオブジェクトに格納できます。 ポインタ指定子とタグビットは、ワードの下位ビットに格納されます。

整数ボックスを整数値として再解釈できるようにするのも良いかもしれません。これは、wasm実装がボックスが整数ボックスであることを証明できる場合は問題ありません。また、整数を整数に変換できるようにすることもできます。ポインタビットをマスクするだけのwasm実装によるボックス。 これには、おそらくどのビットがポインタビットであるかを特定する必要があります。 とにかく、これは整数に対してwordsize-1ビットを提供します。「タグ」は大きい方の値内の単なるビットフィールドです。

@ lars-t-hansenコードがif(is_int(p)) ...を持ち上げると、コンパイラはpがポインタではなく整数としてタグ付けされていることを認識し、最適化できるように、型テスト演算子が必要だと思います。 valof()コンパイラーが巻き上げを行う必要はありません。 ランタイムはとにかく使用時に型をチェックする必要があり、整数はテストする別の型であるため、 ptrof()必要性はわかりません。

「ボクシング」はヒープボックスに割り当てることを意味することが多いため、タグ付けを「ボクシング」と呼ぶかどうかはわかりません。

下位タグビットがマスクされると同時に、上位アドレスビットをテストまたはマスクする機会があり、インデックスが線形ヒープ内にあることを証明します。 私はこれを2年間認識させるために戦ってきましたが、現在MozillaコードのP5である型派生の改善にもっと注意を払う必要があります。少し考えてみてください。

@wllang 、はい、私はまだ頭の中でそれを解決していなかったので、特にそのようなテストに関連するパフォーマンス保証があるかどうか、タイプテストオペコードを省略しました。 is_int(x)はeqz(ptrbitof(x))と同等であり、初心者にとってはそれほど認識しにくいパターンではありません。 is_ptr(x)は単なるptrbitof(x)です。 スタックマシンであるため、架空の1バイト演算「i32.isint」と2つの単項1バイト演算「i32.ptrbit; i32.eqz」で構成される2バイト演算の間には確かに細い線があります。

しかし、正確な形は重要ではありません。重要なのは効果です。 「if(is_ptr(x)){...} else {...}」内で、コンパイラは、値を証明できる場合、xがthenブロックのポインタであり、elseブロックの整数であると想定する必要がありますか?

バイトコードが2つの値になることを許可するとします。 構文を悪用すると、操作ptr_i32.ptrofはポインタ(またはnull)とブール値を返します。 そうすれば、コンパイラが何を「知る」必要があるかについては何の疑問もありません。それは、構造上ポインタである値を持っているだけです。 (これらの型付きオブジェクトの型システムと、どのような意味でポインターが型付けされるかという問題もありますが、それはおそらくタグ付けと直交していると思います。)

(少し逸脱しますが、SPARCのタグ付き追加命令に匹敵する、ある種のステータスコードが返される、特定の単純なタグを持つintボックスで算術演算とビット演算を許可するかどうかについての興味深いアイデアが追加されています。i32x2.addk、 a、bは、aとbの両方が下位kタグビット== 0のintボックスであり、オーバーフローがない場合は(a + b、0)になり、それ以外の場合は(garbage、1)になります。i32x2。またはk、a、b同上a | b。これらの操作は、wasmレベルで効率的に表現するのは難しいですが、ハードウェアレベルで実装するのは簡単です。しかし、これらは専門的すぎて価値がない可能性があります。 Lispish言語からwasmへ。)

上位アドレスビットについては...これについてあなたが以前に何を書いたかはわかりません。 ある種のBiBoPスキームを実装したいですか、それともタグに上位ビットを使用したいですか?

(あなたが言及しているMozillaのバグへの参照?)

Lispish言語をwasmにターゲティングするのは興味深いというケースを作る必要があります

WebAssemblyがすべてのプログラミング言語を効果的にサポートしようとすべきではないと思うなら、Wasmの重要性を過小評価していると思います。 正しく行われると、Wasmが世界を引き継ぎます。 Wasmは、オペレーティングシステム、CPUアーキテクチャ、および(願わくば)プログラミング言語のロックイン能力を低下させます。 オフラインアプリとオンラインアプリ、そしてクライアントとサーバーの両方で、誰もがこれを使用する予定です。

その世界は、特定のプログラミング技術やプログラミング言語が非効率的で非現実的であると運命づけられている世界であってはなりません。WebAssemblyの設計者は、これらの言語はサポートするのに十分「重要」ではないと考えたからです。 私たちが今当たり前と思っていることの多くは、新しい言語の機能と同様に、あいまいな学術言語やLispで始まりました。

私たちの目標は、すべての言語とすべてのプログラミング手法を適切なパフォーマンスでサポート将来の機能のすべて、そしていくつか。 作業に優先順位を付ける必要がありますが、すべてが重要であることを忘れないでください。

@ lars-t-hansen GC /不透明ヒープの設計アイデア(および他のすべてのアイデア)をよりよく理解したいと思います。WebAssemblyVMに関連してタグビットの効果はどのようになりますか?

「万能」VMを作成するにはどうすればよいですか? 何か

  • 正確でコンパクトな世代別GCをサポート
  • 配列スライス、およびオブジェクトまたは配列の先頭だけでなく中央を参照するポインターをサポートします
  • 「薄い」ポインタと「太い」ポインタの両方、または両方に基づくオブジェクトシステムをサポートします。 (細いポインターは、ポイントされたオブジェクトに格納されている型情報に依存しますが、太いポインターは、ポインターの横に1つまたは2つの余分な単語でその情報を格納します)
  • ポインタと整数を動的に切り替えることができる「多分ポインタ」を許可します
  • 共用体型を効率的にサポートします(A、B、またはCへの​​ポインター-それらの1つである必要がありますが、どちらが動的であるか)
  • セキュリティ上の制約の下で可能な範囲で、クライアントがメモリ割り当てとGCを制御できるようにします。
  • 不透明な参照をサポートし
  • 私が考えもしなかった他のものをサポートします

このコメントはOPの問題に固有のものではないという免責事項。

WebAssemblyがすべてのプログラミング言語を効果的にサポートしようとすべきではないと思うなら、Wasmの重要性を過小評価していると思います。 正しく行われると、Wasmが世界を引き継ぎます。

「世界を乗っ取る」ことは、Web Assembly(文字通りおよび比喩的に😉)を狙うための大きな目標ではないと思います。 ブラウザーの大部分が常緑樹である現在、標準は世界でより急速に動いています。WebAssemblyは、プロセッサーに依存するアプリケーション向けに、迅速にシリアル化およびトランスポートに最適化された命令セットで、これらの標準のギャップを埋めるように設計されています。 ランタイムとガベージコレクションを必要とする言語の処理を容易にするいくつかの優れた点を犠牲にして、その要件を可能な限り完全に満たすことに焦点を当てることは、私にとって合理的なことのように思えます。集合的な洞察と経験が蓄積されるにつれて、既存のソリューションに対するソリューションを迅速に改善します。

個人的には、WebAssemblyにはこれらの壮大なアプリケーションの幅を実現するための手段がないと思います。 私は個人的に、Webブラウジングのドキュメント公開の現実に執着することなく、htmlやcssのように安全に共有して楽しむことができる非ブラウザー指向のインターネットベースの仮想アプリケーションの概念の観点からWASMに興味を持ちました。 特に、WebAssemblyの主要な義務が、ISAが特定の問題領域のWebAssemblyであるかどうかにかかわらず、これらすべての種類の可能性を満たすISAの可能性を進める議論から完全に排除されるとは思いません。

「世界を乗っ取る」というのは大きな目標ではないと思います

ただ私の予測。 世界を引き継ぐことが目標だと言っているのではありません。WebAssemblyは独自の位置にあり、誰もそれを実現しようとせずに世界を引き継ぐ可能性が高いと言っています。

では、WebAssembly VMに関連して、タグビットの効果はどうなるでしょうか。 それらは何のため?

上からコメントを抽出して少し詳しく説明したので、毎回このスレッド全体をスキャンしなくても、アイデアが進化するのを見ることができます。
https://github.com/lars-t-hansen/moz-sandbox/blob/master/wasm-tagging.md

その記事には、「なぜタグ付けするのか」という理由ももう少しあります。 セキュリティ、先行技術などに関するコメント。

@ qwertie 、Wasmを妨害したり、特定の言語をサポートできないようにしたりしたくありません。 ただし、WebAssemblyのコンテキストでは、一部のソース言語が他の言語よりも重要であり、一部の言語を適切にサポートするには多大な労力が必要になることを認識しておく必要があります。 Schemeの場合、クロージャ、末尾呼び出し、ファーストクラスの継続、動的に型指定されたオブジェクトフィールド、動的に型指定された変数、および効率的な汎用演算が必要になります。 これらのいくつかは、許容可能なコストで、より単純な構造から実装できます。 末尾呼び出しと継続は、すべてのフレームをgcされたヒープや手動で管理されたスタックにプッシュすることでシミュレートできますが、おそらくそれは望ましくないため、コストがかかりすぎる可能性があります。 したがって、ネイティブサポートが必要になります。 しかし、Schemeがcall / ccの唯一のユースケースである場合、それを受け入れるのは困難な戦いになると思います。 結局のところ、スキームは死語です。

タグ付けの議論は一種の魅力的です。これまでのところ、フェンスの私たちの側での議論は、私たちが持っている必要があるもの(不透明なヒープへのポインター)を取り、多くの人が便利で高性能でポータブルであると感じる安価な機能を追加することについてでした(低ビットのタグ付け)、それからもう1つのアイデア(タグ付けされたもののポインター部分に非ポインターデータを格納する)を開きます。 これは、LispやProlog、その他のいくつかの言語のサポートに大いに役立ちます。

@sebmarkbageは実際に、より一般的なタグ付けスキームについて質問しました。デザインスペースは非常に大きいですが、IMOはユースケースによって推進される必要があります。ユースケースは、おそらく十分に広い言語で、その価値が証明された特定の実装手法です。 「問題」に使用されます。 (そして、その戦略でサポートされていない言語については、それらの言語をWebで実行したい場合は、常にフラットメモリと独自のGCがあります。)

タグ付けの議論は、これまでのところ、私たちが持っている必要のあるもの(不透明なヒープへのポインター)を取り、安価な機能を追加することについての議論であったため、一種の魅力的です。

不透明なヒープへのポインタがWebAssemblyに必要な機能であることに同意しません。 WebAssemblyが動的言語とGCed言語をサポートするための3つの可能な方向性を考えることができます。

  1. GCされていない静的言語に適したVMであることだけを心配してください。
  2. JSで相互運用可能な型指定され、ガベージコレクションされたヒープを公開します。
  3. WebAssemblyで動的型付け言語(または静的型付けGCed言語)を実装するために必要なプリミティブを公開します。たとえば、JITコードのパッチ適用、ガベージコレクション線形メモリのスタックウォーキングなどです。

MVPは、MVP後にコミットすることなく、その範囲を第1方向に制限しました。

この問題とGC設計ページは2番目の方向を想定してい

ただし、WebAssemblyの長期的な方向性としては、3番目の方向性が最適だと思います。 2番目の方向は、WebAssemblyからブラウザーDOMを操作しやすくすることによって動機付けられているようです。 ただし、誰もWebAssemblyで直接コードを記述しないため、言語サポートが必要になります。これにより、手続き型JS APIを使用して、DOMへの低レベルのアクセスがある場合と同じように効果的にDOMにアクセスできます。

2番目の方向では、JVM / .net、Scheme、またはRubyのWASMバックエンドがJavaScriptガベージコレクターを再利用することもできます。 ただし、ガベージコレクターは万能ではありません。多くのアプリケーションのパフォーマンス要件を満たさない型付き+ GCedヒープを含むWASMVMの永続的な要件が導入される可能性があります。

3番目の方向ではより多くの作業が必要ですが、長期的には、よりシンプルなスタンドアロンのWASM VMが可能になり、今日の英雄的な最適化の取り組みの多くがJavaScript VMからWASMサンドボックスに移行するため、ブラウザーVMの複雑さが軽減されます。

以前に#733を作成して、JavaScript GCヒープをWebAssemblyに公開することと、ガベージコレクターを実装するためのプリミティブを公開することの相対的な優先順位について説明しました。 おそらく、WASM GCの方向性についてのさらなる議論はそこで続けることができ、この問題は、GCヒープへの不透明なポインターのサポートがWASMに追加されることを前提として、タグ付きGCポインターに焦点を合わせ続けることができます。

@ lars-t-hansenあなたの記事は、それがガベージコレクションにどのように関連しているか、または不透明な参照のためのメモリ領域のアイデアにどのように関連しているかについて言及していません。 不透明な参照「ヒープ」または「テーブル」は、これらのボックスのいずれかが参照できるような「ボックス」(またはうーん...「タグ付きPtr」... TP)の単純な配列であるという根本的な仮定はありますか? JSオブジェクト、つまりJS GCによって存続しますか?

ドキュメントを調べた後、WebAssemblyにWasm側でガベージコレクションを行わせず、不透明な参照領域にJSオブジェクトへの両方の参照を保持させ(収集されないようにする)、整数やそれ自体への内部参照などの他のもの。 次に、不透明な参照領域をサポートするWebAssembly用の(信頼できない)GCを構築できます。

暖かくなりますか?

ファーストクラスの継続について-これは、私たちが必要かどうかわからない1つの機能です。 コルーチンまたは軽量スタック、確かに、しかし継続? スタックのコレクションとして動作するある種のファイバー/コルーチン/スレッドのものを構築する以外の目的で実際にそれらを使用している人はいますか? たぶん、スイッチスタックオペコードである種の「軽量」スタックのものをサポートするのに十分です。 その場合、 call/ccはWebAssemblyで利用できませんが、人々がcall/ccから構築する傾向があるものは利用できます。

@AndrewScheideckerに同意し

  • 私は相互運用性に深く関心を持っています。 ガベージコレクターが組み込まれていると、ガベージコレクションされたさまざまな言語の相互運用が容易になります。
  • ガベージコレクターは大きなソフトウェアである可能性があり、すべてのWebサイトから異なるGCをダウンロードする必要があるのは面倒な場合があります

したがって、ある種のデフォルトGCが必要だと思いますが、WasmでカスタムGCを実装しても、デフォルトGCを使用することに大きなマイナス面はありません。

@AndrewScheidecker 、フェアポイント-gcされたヒープへの不透明なポインタが必要であることは

@qwertie 、ここでの私の一般的な仮定は、wasmローカルとおそらくタイプPtrとBoxのグローバルがあるということです。 不透明なオブジェクトには、静的にPtrまたはBoxとして入力されるフィールドが含まれる可能性があります。 また、システムのGCがこれらのフィールドをトレースし、その内容に関する完全に信頼できる情報を持っていること。 アイデアは、ここでは、別のタイプのプロジェクトと考える、あるタイプのプラグ可能なGCをサポートすることではありませんでした。 (繰り返しになりますが、この議論は「不透明なポインターにタグを追加できますか?」として始まりました。)

2017年1月4日水曜日午後2時59分、Andrew Scheidecker < [email protected]

書きました:

タグ付けの議論は、これまでのところ、
フェンスの私たちの側での議論は、私たちがしなければならない何かを取ることについてでした
持っている(不透明なヒープへのポインタ)そして安価な機能を追加する

不透明なヒープへのポインタがWebAssemblyの機能であることに同意しません
持つ必要があります。 WebAssemblyの3つの可能な方向性を考えることができます
動的言語とGCed言語のサポート:

  1. GCされていない静的言語に適したVMであることだけを心配してください。
  2. JSで相互運用可能な型指定され、ガベージコレクションされたヒープを公開します。
  3. 動的型付けを実装するために必要なプリミティブを公開します
    WebAssemblyの言語(または静的に型指定されたGCed言語):例:JIT
    コードのパッチ適用、ガベージコレクションの線形メモリのためのスタックウォーキングなど。

MVPは、その範囲を第1方向に限定しました。
それはMVP後です。

はい、これはフィーチャークリープに抵抗し、確実にするために非常に意図的でした
成功。

さまざまなコンテキストで説明したのは、_extension_としての管理対象データです。
WebAssemblyへ(私はManaged Data Extensions、またはMDXという名前も考えています。
良い候補になるために)。 マネージドデータ拡張により、WASMコードが許可されます
線形メモリとは別に低レベルの構造体を割り当てる
WASMエンジンによって管理(つまりGC)されます。 構造体は次のように入力されます
ボックス化されていないフィールドであり、実装を可能にするのに十分な低レベルになります
Javaのような高級言語のオブジェクトモデル(vtables、クラスを使用)
ポインタなど)、Go、関数型言語など。

管理対象のデータ型、値、および演算子を拡張機能として配置する
単純に実行するコアWASM実装を持つことが可能になります
拡張機能をサポートしていません。 そのような実装では、それは可能です
(多少の作業は必要ですが)を使用する自動翻訳を実装するには
これらをエミュレートするための線形メモリ(または別の線形メモリ)の一部
パフォーマンスは低下しますが、GCを構築および実装します。

この問題とGC設計ページhttp://GC.mdは、2番目の問題を想定しています。
方向。 その仮定の文脈では、GCのタグビットを公開します
ポインタは不透明なGCポインタの安価な拡張として意味があります
それは「サポートされなければならない」。

しかし、私は3番目の方向が最良の長期的な方向であると信じています
WebAssembly。 第二方向は、より簡単にすることによって動機付けられているようです
WebAssemblyのブラウザDOMを操作します。 しかし、誰も書いていません
WebAssemblyで直接コーディングするため、言語サポートが必要になります。
手続き型JSAPIを使用して、同じようにDOMにアクセスできます。
DOMへの低レベルのアクセスがあるかのように効果的に。

2番目の方向では、JVM /.netまたはSchemeのWASMバックエンドも許可されます。
またはRubyでJavaScriptガベージコレクターを再利用します。 しかし、ゴミ
コレクターは万能ではありません:可能性のある結果は
タイプ+ GCedを含めるためのWASMVMの永続的な要件の導入
多くのアプリケーションのパフォーマンス要件を満たさないヒープ。

3番目の方向はより多くの作業が必要ですが、長期的には両方が必要です
よりシンプルなスタンドアロンWASMVMを可能にし、ブラウザーVMの複雑さを軽減します
今日の英雄的な最適化の取り組みの多くがJavaScriptVMから移行するにつれて
WASMサンドボックスに。

以前に#733を作成しました
https://github.com/WebAssembly/design/issues/733で
JavaScriptGCヒープをWebAssemblyに公開することの相対的な優先度と
ガベージコレクタを実装するためのプリミティブを公開します。 おそらくさらに
WASM GCの方向性についての議論はそこで続けることができ、この問題は
サポートすることを前提として、タグ付きGCポインタに焦点を合わせ続けることができます
GCヒープへの不透明なポインタ用にWASMに追加されます。


あなたが言及されたのであなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/WebAssembly/design/issues/919#issuecomment-270484689
またはスレッドをミュートします
https://github.com/notifications/unsubscribe-auth/ALnq1EpdSRskLiuHx4v5M83T4IS9wmx1ks5rPAgggaJpZM4LPxE5

@ lars-t-hansen、整数には明示的なタグ付け/タグ付け解除が必要であることは明らかですが、型システムでボックス化された参照型とボックス化されていない参照型を区別するためのユースケースは何ですか? ボックス化された参照で直接提供できなかった、ボックス化されていない参照に対する操作はありますか? その場合、前者を紹介する必要はありません。

@titzer Re: 'これらの構造体をエミュレートしてGCを実装しますが、パフォーマンスが低下します'-線形メモリを使用するwasmコアがパフォーマンスの低下なしにGCを含むオブジェクトシステムを実装できない場合、それはコア設計の問題のようです。

これらの「パフォーマンスの欠点」の性質は何ですか?

これらの関連プロジェクトでの私の経験からの私の解釈は、Webブラウザーベンダーが問題の一部である、または合意を得ることは信じられないほどの課題であり、したがってコミュニティが必要としているのはWebブラウザーベンダーが高性能で低レベルを提供することであるということです。開発がWebブラウザベンダー間の合意を持つ必要から解放されることができるように言語。 したがって、私はWebコミュニティの利益のためにその目標に焦点を合わせ続けることをアピールし、管理対象オブジェクトはその目標から気をそらすものです。

上位レベルのマネージドオブジェクトとマネージドGCをwasmから削除し、将来の機能から削除し、コアに焦点を当て、線形メモリ内のオブジェクトシステムとGC実装でパフォーマンスの問題があるグループに報告してもらいます。コアデザインの課題で検討されました。

線形メモリ内のタグ付きポイントとこれらに対処するためのパスに関するいくつかの課題はすでにわかっています。私が試したが、これまでのところ合意を得るために失敗した、改善された整数型の派生です。 この派生をよりクリーンにするためのSSAエンコーディングの潜在的な利点。 下位ビットをマスキングしながら上位ビットをマスキングすることの利点。

上位レベルのマネージドオブジェクトとマネージドGCをwasmから削除し、将来の機能から削除します

私はこの見解に強く反対します。 管理対象オブジェクトは、管理対象言語からコンパイラー作成者の生活を簡素化することではありません。 マネージドメモリによって将来的にwasmにもたらされる主な具体的な機能は、JavaScriptの世界の他の部分とのあらゆる種類の対話を可能にする

線形メモリモデルで、wasmメモリからJavaScriptオブジェクトへの(循環する可能性のある)参照を実装する方法はありません。 このコア要件が最終的に対処されない限り、ClojureScript、Scala.js、またはJavaScriptとの適切な相互運用性を備えた他のコンパイルからJSへの言語が、代わりにwasmにコンパイルされることは期待できません。

言語内機能を何にでもコンパイルするのは簡単です。 そのためのターゲットサポートは本当に必要ありません。 ただし、言語機能のコンパイルは、ターゲットからのサポートなしでは不可能です。 IMO wasmは、最終的にJavaScriptオブジェクトモデルと相互運用するためのすべてのツールを提供するはずです(そして、この共通モデルを通じて、コンパイルからwasmへの言語間で)。 そして、それには、wasm仕様に組み込まれたマネージドメモリモデルが必要です(そのようにブランド化したい場合は、拡張機能として使用できる可能性があります)。

@sjrdこれらの「課題」を詳細に把握して、対処できるようにするとよいでしょう。 したがって、あなたが上げているように見えるショーストッパーは次のとおりです。

  • wasmサンドボックス内の整数をJSオブジェクトにマッピングしますが、これはハッシュテーブルまたは配列を使用してかなり可能であるように思われます。これはどれだけ効率的であり、どれだけ効率的である必要がありますか? これはすでにゲームなどで行われています。ポインタのセキュリティを満たすより効率的なハッシュが可能かもしれないので、必要に応じてこれを調べてみましょう。

  • また、循環参照の問題を提起しているので、JSGCがwasmVMに整数として格納されているこれらのGCポインターをどのようにスカベンジできるかが懸念されていると思いますか? しかし、JSから線形メモリ内のオブジェクトへのポインタもどうでしょうか?

これらの問題は、一般にwasmコードが管理対象オブジェクトと管理対象GCを使用し、基本的にコアwasmプロジェクトをあきらめてそれをより高いレベルのVM設計。

そこで、いくつかの解決策を探ることができます。wasmサンドボックスを呼び出してJSオブジェクトを参照する可能性のあるポインターをスカベンジし、これらをJSGCに通信するための定義済みの方法を持つJSGCフックです。 これは、wasmコアの設計とサンドボックスに負担をかけないいくつかの定義済みFFI呼び出しである可能性があります。 これは、すべての問題を解決するためにwasmに頼る誘惑に駆られることなく、発生する必要のあるタイプの考え方です。

@sjrdまた、「分散ガベージコレクション」を検索することもできます。これは、wasmに負担をかけることなくユースケースに対処できるフレームワークである可能性があります。 JSが必要なすべてのサポートを備えているかどうかはわかりませんが、必要に応じて、クラウドオブジェクトストアなどのJSにそのサポートを追加することに、より一般的な関心があるかもしれません。これは、wasmCGの外部で行うことができます。 wasm側は整数のwasmコードであるため、個別のプロジェクト(または、WebブラウザーベンダーやWebコミュニティが同意できない場合は複数のプロジェクト)である可能性があります。 おそらく多くのアプリでは、参照カウント、ウィークポインター、リースポインターなどの単純な戦略で、wasmインスタンスとJSインスタンス全体のグローバルガベージコレクションが複雑になることなく適切です。 別のオプションは、これらのフレームワークのJSコードの多くをサンドボックスに移動できるかどうかを確認することです-誰かが、より大きなコードベースのごく一部であるその他のJSコードに対して十分なパフォーマンスを持つwasmのJSインタープリターを作成しますか?

@ rossberg-クロム、

整数には明示的なタグ付け/タグ付け解除が必要であることは明らかですが、型システムでボックス化された参照型とボックス化されていない参照型を区別するためのユースケースは何ですか? ボックス化された参照で直接提供できなかった、ボックス化されていない参照に対する操作はありますか? その場合、前者を紹介する必要はありません。

ボックスが参照を保持しているかどうかはわかりません。 そのため、Boxで直接ポインタ操作を行うと(それ自体は問題ありません)、ポインタビットをチェックしてタグを削除する必要があります。 Ptrでのポインタ操作では、これを行う必要はありません。 したがって、私の観点からは、これは単なる効率の問題でした。

@ lars-t-hansen、ああ、IIUCのrawポインターは入力されますが、ボックス化されたポインターは入力されませんか? AFAICS、それはあなたが望む因数分解ではありません。なぜなら、ボックス化されたポインターを介したすべてのアクセスは最初にランタイムチェックを必要とするからです-そしてボックス化されたポインターはあなたがGCedメモリに保存できる唯一のものです。 したがって、メモリグラフを歩くには、すべてのエッジでランタイムチェックが必要になります。

私は少し違うことを考えていました。不透明な参照型のファミリーref(T)です。ここで、Tは構造体/配列、関数(つまり、関数ポインター)、または整数(つまり、タグ付きint)のいずれかです。 さらに、すべての参照の和集合/スーパータイプであり、タイプテストとチェックされたダウンキャストを実行できるタイプanyrefがあります。 そうすれば、実際にユニオンを扱っているときにのみランタイムテストが必要になります。 さらに、nullはタイプanyref値ですが、 ref(T)ではないため、nullチェックも同様に分離でき、コードで明示的になります。

@ rossberg-chromium、確かに私はここでタイプ情報を追跡する方法について詳しく説明しました。 Boxesがタイプ情報、つまりBox(Ptr)ここで、Tは構造体タイプであり、Tへのタグ付きポインターまたは(タグ付き)整数のいずれかを保持することがわかっているデータを生成します。 その場合、ボックスを直接逆参照する場合でも、ポインター性をチェックする必要があり(intの場合もあります)、タグを削除する必要があります(タグに不明なビットが設定されているため)。

あなたのref(T)のアイデアは明確に関連していますが、私が正しく理解していれば、少なくともユーザー定義のタグではなく、ポインターにタグを付けることはできません。これは、私の設計で解決しようとしていた問題です。

(型システムを介してnullptrを制約する場合は+1ですが、これはタグに直交すると思います。)

@ lars-t-hansen、なるほど。 ええと、タイピングは実際にはタグ付け機能の核心だと思います。 もう一度考えてみると、Wasm型システムにタグ付き型または合計型を明示的に導入せずにそれを達成する方法がわかりません(依存型のいくつかの形式は避けたいと思います)。

しかし、とにかく何らかの形式のタグ付きタイプが必要な場合は、このより高いレベルの抽象化でタグ付けを完全にモデル化し、最低レベルのポインター値に干渉しない方が魅力的です。 これにより、実装に適切と思われる最良の方法でタグを格納するために必要な余裕が与えられ、アーキテクチャとVMの両方への依存、またはタグを共通の分母に制限することが回避されます。 たとえば、V8の場合、ポインタに複数の追加タグビットをサポートするには、基本的にV8の半分を再実装する必要があります。これは、特に32ビットプラットフォームでかなりのメモリコストがかかるため、サインアップする可能性はほとんどありません。 一方、V8には、各値のスペースを無駄にすることなく、ヒープ値のマップ(「非表示クラス」)に大きなタグを効率的に格納するための多くの方法があります。

@wllang

これらの「課題」を詳細に把握して、対処できるようにするとよいでしょう。

同意します。 私はしばらくの間これを行うことを計画していましたが、まだそれを行うことに慣れていません。

wasmサンドボックス内の整数をJSオブジェクトにマッピングしますが、これはハッシュテーブルまたは配列を使用してかなり可能であるように思われます。これはどれだけ効率的であり、どれだけ効率的である必要がありますか?

IMOは、JavaScriptでヒープオブジェクトます。 整数マップでは、このレベルのパフォーマンスに近づくことはできないと思います。

ここや他のスレッドでのいくつかの投稿から判断すると、アンマネージ言語に関しては、wasmコアのパフォーマンスについて非常に懸念しているようです。 ただし、マネージド言語とその優先順位については、wasmとのより深い統合と比較して、本質的に最適ではなく、パフォーマンス面での回避策ソリューションに関する主要な懸念を回避します。 なぜ私たちはそのように管理された言語を区別する必要がありますか?

これらの問題は、一般にwasmコードが管理対象オブジェクトと管理対象GCを使用し、基本的にコアwasmプロジェクトをあきらめてそれをより高いレベルのVM設計。

たとえば、wasmに2つのメモリスペースがある場合、これに対処できます。現在の線形メモリ。主に、wasmにコンパイルするアンマネージ言語で使用されます。 また、JavaScriptヒープとのジョイントGCをサポートするGCのヒープは、主にwasmにコンパイルされるマネージド言語で使用されます。 マネージド言語は、おそらく「オフヒープ」割り当てにも線形メモリを利用することに注意してください(たとえば、JavaのByteBuffer.allocatedDirect() )。 また、アンマネージド言語は、JavaScriptとの相互運用性シナリオにマネージドメモリを利用する可能性があります。

これは、wasmコアの設計とサンドボックスに負担をかけないいくつかの定義済みFFI呼び出しである可能性があります。

私はGCの専門家ではありませんが、「GCへの公的に指定されたフックのほんの一部」がwasmコアの設計やVMの実装に大きな負担をかける可能性があると感じています。

別のオプションは、これらのフレームワークのJSコードの多くをサンドボックスに移動できるかどうかを確認することです-誰かが、より大きなコードベースのごく一部であるその他のJSコードに対して十分なパフォーマンスを持つwasmのJSインタープリターを作成しますか?

これは、関係するすべての人にとって非常に高い全体的な負担になります。 そしてTBH、ほとんどの場合、wasmが実際のJS VMにリンクされている場合、wasm内にJSVMを実装するのは本当にばかげていると感じます。 その上、それは本質的にJavaScriptAPIであるブラウザAPIとの通信の問題を解決しません。

@sjrd

IMOは、JavaScriptでヒープオブジェクトを操作する同じコードを記述するのと少なくとも同じくらい効率的である必要があります。 整数マップでは、このレベルのパフォーマンスに近づくことはできないと思います。

配列へのインデックス作成は高速で、おそらくいくつかのマシンコード命令です。 ハッシュルックアップはヒットでも同様です。 JS JITは、内部でテーブルとテストを備えた多くのキャッシュを使用するため、パフォーマンスはJSの特性である可能性があります。

ここや他のスレッドでのいくつかの投稿から判断すると、アンマネージ言語に関しては、wasmコアのパフォーマンスについて非常に懸念しているようです。 ただし、マネージド言語とその優先順位については、wasmとのより深い統合と比較して、本質的に最適ではなく、パフォーマンス面での回避策ソリューションに関する主要な懸念を回避します。 なぜ私たちはそのように管理された言語を区別する必要がありますか?

「マネージド言語」を定義すると、同じように聞こえない場合があります:) Wasmは、wasmコアコードで記述され、wasm線形メモリに格納された効率的なオブジェクトシステムをサポートできるはずです。このコードは、オブジェクトシステムを「管理」します。サンドボックスで記述された他のコード、そして私はこのユースケースのパフォーマンスを向上させるために数年前から取り組んできました。 したがって、私は一般的に「マネージド」コードに偏見を持っていません。Cコードのパフォーマンスだけに焦点を当てているわけではありません。

懸念していると思われるのは、同じプロセスアドレス空間で動作するJSランタイムによって管理されるオブジェクトとの統合です。 しかし、wasmの実装がwasmサンドボックスを別のサンドボックス化されたプロセスに配置したいとしているとしましょう。あなたはすでに懸念していると思われるユースケースの範囲外に踏み出しました-そして、wasmインスタンスを別のプロセスに配置することは魅力的かもしれませんセキュリティとパフォーマンス。

たとえば、wasmに2つのメモリスペースがある場合、これに対処できます。現在の線形メモリ。主に、wasmにコンパイルするアンマネージ言語で使用されます。 また、JavaScriptヒープとのジョイントGCをサポートするGCのヒープは、主にwasmにコンパイルされるマネージド言語で使用されます。

外部ポインタを線形メモリに格納できないため、線形メモリ内のオブジェクトシステムはそれらを格納できず、実用的ではないため、管理された外部ポインタを使用してオブジェクトシステムを実装する必要があります。 確かに、コードは線形メモリにいくつかのバッファなどを割り当てることができますが、外部ポインタと統合された線形メモリ内の独自のオブジェクトを管理することはできませんでした。

私はGCの専門家ではありませんが、「GCへの公的に指定されたフックのほんの一部」がwasmコアの設計やVMの実装に大きな負担をかける可能性があると感じています。

一部のインポート/エクスポートされた関数名を定義することは、wasm設計の負担ではありませんが、JS GC実装の​​負担はかなりのものであり、グローバルGCがショーストッパーであるかどうかを考える必要があります。

これは、関係するすべての人にとって非常に高い全体的な負担になります。 そしてTBH、ほとんどの場合、wasmが実際のJS VMにリンクされている場合、wasm内にJSVMを実装するのは本当にばかげていると感じます。 その上、それは本質的にJavaScriptAPIであるブラウザAPIとの通信の問題を解決しません。

Wasmの消費者の負担ははるかに少なくなります! はるかに低い攻撃対象領域。 また、(別のプロセスで)より高いパフォーマンスとより安全な実装を可能にする場合もあります。 また、設計の負担もはるかに少なくなります。これは非常に重要なようです。実装を作成するように契約する人と比べて、Webブラウザーに機能をデプロイするのにどれだけの労力とリソースが必要になると思いますか(成功する可能性がある場合)。 wasmコアの機能について、リソースの10倍または100倍を見積もりますか。また、成功の可能性は、おそらく10分の1または100分の1でしょうか。

また、wasmインスタンスが別のプロセスにある可能性があり、そのwasmがキャッシュされる可能性のあるVMコードとリンクできる可能性があり、Webブラウザーがバージョンとそれを交換するメカニズムにバンドルされている可能性があることを考えると、おそらくそれほど「ばかげている」わけではありません。 JS VM(wasmサンドボックスで使用するため)をユーザーが選択またはアップグレードしたり、デバッグなどのために別のバージョンに交換したりできることを想像してみてください。これは、エコシステムを開いてJSをアンバンドルすることでもあることに注意してください。ある程度、人々は小さな基本的なインタープリター、マイクロパイソン、LUA、CIL VM、JVMなどを含めるかもしれません。とにかく単純なJSインタープリターはどれくらい重いですか、比較的重い場合は、おそらく他のフレームワークがとにかく利点を示しますか?

OSレイヤーのようにJSオブジェクトを処理する必要なしに、wasmインスタンスで利用できるようになる低レベルのJavaScript APIをサポートしますが、それはかなり可能だと思われます。

また、ご希望のJS VMを表現するのに十分な柔軟性を備えたwasmエンコーディングもサポートします。これはそれほど大きな負担ではないようで、とにかく将来を見据えたwasmに役立ちます。 Web上で高性能で低レベルのVMを見るために生きるかどうか疑問に思います。

@ rossberg-クロム

一方、V8には、各値のスペースを無駄にすることなく、ヒープ値のマップ(「非表示クラス」)に大きなタグを効率的に格納するための多くの方法があります。

ここで説明しているポインタタグはクラスごとではなくポインタごとであるため、ポインタタグを「クラス」オブジェクトに格納することを提案するのは少し奇妙に聞こえます。おそらくv8はポインタを複数の単語に格納しますが、それは驚くべきことです。面白いデザイン? オブジェクトはタグビットにエンコードされた即時値である可能性があるため、ポインタが指しているオブジェクトにこれらのタグを格納することもできません。

@sjrd GCの問題にこのフォーラム(特許)で提起された解決策があることを確認するために、ここに1つの解決策があります。 JS GCは、JSポインターと整数(wasm側ポインター)の間でマップする新しいテーブルを追加します。 テーブルのwasm側を線形メモリに直接維持する可能性があるため、JSテーブルは配列バッファと範囲を参照します。 両側にliveフラグとポインタごとの参照カウントがあります。 テーブルにポインタが追加されると、ライブフラグが設定され、テーブルのその側で参照カウントが1に設定されます。 いずれかの側のGCが実行されると、最後までこれらのテーブルの清掃が延期されるため、その時点で、それぞれの側のこれらのポインターがテーブルの外側からその側からのライブポインターを持っているかどうかを認識し、それぞれの側のライブフラグを更新します。 ライブフラグがクリアされ、反対側の参照カウントがゼロの場合、ポインタは再利用され、テーブルから削除されます。 これらすべてのテーブルを処理した後、GCは、参照するものをすべてライブに保ちながら、ライブポインターを清掃し続けます。 JS側では、これらのポインターは書き込み専用であるか、JS側でライブではないとフラグが付けられると読み取り不能になります-wasm側GCは同様のセマンティクスに従うことが期待されます(テーブルを保持する線形メモリは引き続き読み取り可能ですが、コードは強制します読み取り可能ではないというオブジェクトシステム不変)。 いずれかの側のGCの後、ライブではないとフラグが付けられたポインターがある場合、非同期呼び出しがトリガーされます。これは、参照カウントを更新するために反対側を呼び出すことができ、ゼロになると、ポインターは次のGCで再利用されます。 これらのテーブルは、同じスレッド外のオブジェクトストアのグローバルGCに使用でき、JSコミュニティの間でこのような機能にもっと一般的な関心があるかもしれません。

@ wllang 、マップ/非表示クラスは、個々の値の表現を追跡するための一般的な実装手法です。 それらは、クラスの言語レベルの概念と大まかに関連しているだけです。

@ rossberg-chromium v​​8の隠しクラスについて私が理解していることから、それらはオブジェクトのスロットとして格納されます。 このPRはタグ付きポインタに関するものであるため、タグを別のオブジェクトスロットに格納することも関係がないようで、非表示のクラスにタグを格納することはほとんどありません。むしろ、ポインタに格納する必要があるため、実装はどのビットを自由に決定できるかしかわかりません。使用するポインタの数。 それとも、私が理解していない何か他のことを考えていましたか。 おそらく、これらのスライドは他の人を助けるでしょうhttp://thlorenz.com/talks/demystifying-v8/talk.pdf

@wllang 、私が言ったことは、アーキテクチャとVMには厳しく、大きく異なる制約があるため、タグが実際に格納されている場所を公開することはおそらく意味がないということです。 Wasmのタグ付けサポートは、複数の実装戦略を可能にするために十分に抽象的である必要があります。

可能な拡張機能としてGCプロポーザル(https://github.com/WebAssembly/gc/)に含まれています。

ねえ@ lars-t-hansenと@ qwertie—私はここで外れ値になります。 継続は、尊重されない1つの機能です。 そして、人々は彼らを困難な方法で再発明しなければならないことになります。 それらを取得すると、自動的にコルーチン、マイクロスレッド、ジェネレーター、ゴルーチン、あなたが持っているものを無料で入手できます。 _そして_あなたは、以前は想像もしていなかったものをさらに構築するためのプリミティブを持っています。 例えば:

  • Pyretのreactor機能とDrRacketのbig-bang機能は、プログラミング言語で一流のイベントループ抽象化を提供します。 ブラウザに実装するには、継続のようなサポートが必要です。

  • DrRacketのsend/suspend機能(Smalltalk Seasideフレームワークや他の多くのフレームワークによって模倣されているため)—直接スタイルのサーバーサイドWebプログラミング用—ほぼ完全に継続が必要であり、それらがある場合は簡単に実装できます。

これらはどちらもcall/cc自体ではないことに注意してください。これは無関係で気の利いたプログラマーの抽象化であり、継続を使用して簡単に作成でき、それなしでは作成できません。

WeScheme [http://www.wescheme.org/]とPyret [https://www.pyret.org/]の両方の実装者は、それが不足していることに対して多額の代償を払っています。 両方とも、プログラム変換によってそれを取得し、これらの種類の機能を有効にするために、多大なパフォーマンスのペナルティと複雑さのオーバーヘッドを伴いながら、苦痛を伴いながらゆっくりとスローします。

独自の_ユーザー向けプログラミング言語_を構築している場合は、「ローカル以外の制御の転送は行わないことを宣言します」と言うのは完全に合理的です。 _アセンブリ_を構築している場合は、「継続は奇妙で、Schemeだけがとにかくそれらを持っていて、誰がそのことについてSchemeを使用するか」を超えて考え、現代語が持っている多数の実行制御プリミティブを検討し、人々が発明し続けていると思います。 。

ブラウザの人々は継続もコルーチン/スタック切り替えもサポートしないことに決めたので、それは議論の余地がありますが、私は興味があります-これらの機能が何をするのか説明できますか?コルーチンを使用してこれらの機能を構築できない理由を理解できます/ stack-プリミティブとしての切り替え?

ほとんどの場合、コルーチンで十分です。 彼らは確かにトリックをします
ここ。

こんにちは@shriram 、私たちはC ++を超えて考えており、これらの機能を奇妙なものや重要でないものとは見なしていないので安心してください。 それらをサポートすることは、MVP後の議題にあります。 必ずしも一般的なcall / ccを追加する必要はないかもしれませんが、より限定された形式の区切られた継続はありそうにありません。 考えられる方向の1つは、代数効果ハンドラーです。構造化例外処理の提案はすでにあります。再開を追加することは、構造化形式の「スタックスイッチング」を提供し、言及したすべての制御抽象化を有効にするための「最も簡単な」方法です。 。

このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

chicoxyzzy picture chicoxyzzy  ·  5コメント

artem-v-shamsutdinov picture artem-v-shamsutdinov  ·  6コメント

mfateev picture mfateev  ·  5コメント

aaabbbcccddd00001111 picture aaabbbcccddd00001111  ·  3コメント

JimmyVV picture JimmyVV  ·  4コメント