Go: all: Unterstützung für WebAssembly ("wasm")

Erstellt am 2. Feb. 2017  ·  147Kommentare  ·  Quelle: golang/go

WebAssembly ("wasm") ähnelt Native Client, unterscheidet sich jedoch insbesondere dadurch, dass andere Browser planen, es zu implementieren.

http://webassembly.org/

Dies wurde ein paar Mal gefragt, also ist dies ein Tracking-Bug dafür.

Ob wir es über cmd/compile, gccgo oder llvm-go erhalten, wir können hier Updates veröffentlichen.

Arch-Wasm NeedsFix

Hilfreichster Kommentar

Hallo allerseits. Hier ein Update zu meiner Arbeit: Ich mache sehr gute Fortschritte, was vor allem der großartigen Arbeit des Go-Teams und der Mitwirkenden zu verdanken ist. Der größte Teil des Codes wird von Architekturen/Plattformen gemeinsam genutzt, sodass nicht so viel implementiert werden musste, wie ich erwartet hatte.

Hier ist eine Liste von Dingen, die bereits gut funktionieren:

  • Ausführen des generierten Wasm-Codes in Browsern und in Node.js
  • grundlegende Operationen, Konvertierungen usw.
  • Schnittstellen
  • Goroutinen & Kanäle
  • aufschieben/Panik/Rettung
  • Lesen von Dateien von der Festplatte bei Verwendung von Node.js
  • Tests der folgenden Pakete werden bestanden: bytes, container/heap, container/list, container/ring, encoding/ascii85, encoding/asn1, encoding/base32, encoding/binary, encoding/csv, encoding/hex, errors, flag, hash/adler32, hash/crc32, hash/crc64, hash/fnv, html, image, image/color, index/suffixarray, math, math/bits, path, sort, strconv, strings, text/scanner, text/tabwriter, unicode, unicode/utf8, unicode/utf16

Einige Dinge, die noch bearbeitet werden müssen:

  • Betrachtung
  • den Stapel von Goroutinen wachsen lassen
  • Müllabfuhr
  • Leistungsoptimierungen
  • wasm-Dateigrößenoptimierungen
  • eine schöne JS-Interop-Schicht
  • viele andere Probleme, um mehr Pakettests zu bestehen

Ich freue mich sehr über die Fortschritte in anderthalb Monaten und nur in meiner Freizeit. Ich denke, es besteht eine gute Chance, dass wir dies in Go 1.11 einbauen könnten. Erwarten Sie mein nächstes Update im Januar, da ich im Urlaub bin und dann sind da die Feiertage.

Alle 147 Kommentare

@cherrymui und ich haben die Möglichkeit eines Wasm-GC-Ports ausführlich diskutiert
die letzten paar Tage:

Unsere aktuelle Schlussfolgerung ist, dass es keinen effizienten Weg zur Implementierung gibt
setjmp/longjmp-Funktionalität derzeit, daher ist es kein praktikables Ziel
eines GC-Ports. Wir müssen warten, bis es zum echten Stapelabbau kommt
Unterstützung der Ausnahmebehandlung.

Alle anderen Aspekte sahen gut aus, und wir haben sogar ein Go ABI unter Wasm entworfen
(g und SP auf Wasm-Stack und alles andere auf emuliertem Go-Stack übergeben) und
Eine Möglichkeit, das aktuelle MIPS-Backend so zu ändern, dass es Wasm unterstützt, indem MIPS emuliert wird
registriert sich als lokale Wasm-Variablen.

Vielleicht kann GopherJS Wasm einfacher unterstützen.

Aus gopherjs/gopherjs#432:

Es ist jedoch keine Technologie, die GopherJS verwenden kann. GopherJS kompiliert auf AST-Ebene, nicht auf Maschinencode-Ebene.

WebAssembly könnte als Backend für den normalen Go-Compiler verwendet werden

@minux Das Fehlen von Threads oder asynchroner E/A scheint ein größeres Problem zu sein als die ABI-Problemumgehungen, die wir aufgrund von Wasm-Macken durchführen müssten.

@minux , @cherrymui
könntest du irgendwo detaillierter posten, was du getan und erreicht hast?
Wie Sie vielleicht wissen, erwägt die Go-Interpreter-Community, einen Interpreter zu schreiben, der entweder auf LLVM- oder Wasm-Bytecode basiert.
(Wir haben vielleicht sogar einen GSoC-Studenten, der am wasm-Bytecode-Interpreter [1] arbeitet, also nur den Teil „Bytecode-Verbrauch“, nicht den Teil „Bytecode-Erzeugung über eine Go-basierte Toolchain“.)

die Minimierung des doppelten Aufwands und der Impedanzfehlanpassung zwischen verschiedenen Komponenten wäre großartig.

Ich empfehle dies als strategisches Feature. Bedenken Sie, dass in nur wenigen Jahren Webprogrammierer in Horden zusammenströmen werden, um ihre bevorzugte Sprache auszuwählen, die in Webassembly kompiliert werden soll. Je früher wir ins Rennen einsteigen, desto besser. Mozilla treibt Rust als bevorzugte Web-Assembler-Sprache voran ...

Ich stimme dem zu, was @RaananHadar gesagt hat. Es wäre schade, wenn die Spezifikation nicht den Anforderungen von Go entsprechen würde, insbesondere wenn man bedenkt, wie einzigartig die Laufzeit von Go sein kann.

EDIT: Entschuldigung für die MeToo-Natur dieses Kommentars :) Danke für den Hinweis Brad.

Der Maschinenkontext des WebAssembly-Stapels besteht aus linearem Speicher und einem Operationsstapel. IIUC, das Speichern des VM-Kontexts kann möglicherweise durch Speichern erfolgen von:

  1. Aktueller PC, Bytecode-String
  2. Linearer Speicher und die
  3. Operationsstapel

Zu einer globalen Liste gespeicherter Kontexte in der VM-Kontextstruktur, falls vorhanden.

Daher sollte ein Setjump diese Werte einfach wiederherstellen und mit der Interpreter-Schleife wie gewohnt fortfahren (Dies ähnelt der Art und Weise, wie die Emacs-Bytecode-VM Signale implementiert: https://github.com/emacs-mirror/emacs/blob/master/src /bytecode.c#L785). Darüber hinaus kann ein Ausnahmesystem implementiert werden, obwohl ich nicht sicher bin, wie leistungsfähig dies wäre.

Darüber hinaus erwähnt die Webassembly-Spezifikation, dass die Stack-Höhe zu jedem Zeitpunkt im Bytecode statisch bekannt ist, wodurch alle Stack-Operationen äquivalent zu Operationen an Registern sind, die für jede Position auf dem Stack eindeutig sind. Dieses Dokument beschreibt einen Weg, um eine solche Stack -> Register-Zuordnung zum Konvertieren von Stack-Maschinencode in nativen Code zu erreichen, sodass wir wie gewohnt setjmp/longjmp verwenden können.

Bearbeiten: Was ist mit der Verwendung panic() und recover() mit speziellen WasmException{} -Werten zum Signalisieren einer Ausnahme? recover erledigt bereits die schwierige Aufgabe des Stack-Unwinding, es sollte nicht schwer sein, die Interpreter-Schleife nach der Wiederherstellung einer abgefangenen Ausnahme wiederherzustellen.

Ja, im Grunde führte die Diskussion mit @cherrymui zu ähnlichen Erkenntnissen.

Das ursprüngliche Design mit @cherrymui sieht folgendermaßen aus:
(Diese Phase konzentriert sich darauf, $GOROOT/test/sieve.go zum Laufen zu bringen, kein asynchrones IO ist
betrachtet.)
Wir verwenden den MIPS-Port wieder und ordnen die 31 MIPS-Register als lokales WASM zu
Variablen und verwenden Sie nur den WASM-Stack
für Zwischenergebnisse. Wir können den Funktionsaufrufmechanismus von WASM nicht verwenden
Die meisten Go-Funktionen, weil
das Fehlen einer Stütze zum Abwickeln des Stapels.
Ändern Sie den Mips-Objlink (cmd/internal/obj), um jede MIPS-Anweisung zu emulieren
mit entsprechenden WASM-Anweisungen.
Dies macht die Implementierung von setjmp/longjmp (auch bekannt als runtime.gogo) trivial und
verwendet einen Großteil des vorhandenen Aufwands wieder.

Go muss bereits einen eigenen Stack implementieren, der vom WASM-Stack getrennt ist.
weil Go kopierbar sein muss
Stack, Stack-Pointer-Maps und Stack-Unwinding-Unterstützung, was nicht der Fall ist
erhältlich bei WASM.
(Diese Strategie stimmt auch mit dem LLVM-Port überein, für den wir keinen LLVM-Stack verwenden können
fast die gleichen Gründe
(es sei denn, wir fügen einen benutzerdefinierten Backend-Pass zu LLVM hinzu, um den Stapelzeiger zu codieren
Karten).)

Wir müssen wahrscheinlich einen großen Schalter verwenden, um indirekte Sprünge einzufädeln? Das ist
ähnlich dem Ansatz von NestedVM.
http://nestedvm.ibex.org/

Wenn wir uns entscheiden, ein natives WASM-Backend zu implementieren, können wir Folgendes tun:
das Go ABI ist:
alle Parameter (einschließlich Ergebnisse) auf (emuliertem) Go-Stack,
Beim Funktionseintritt befindet sich Folgendes auf dem WASM-Stack:
emulierter SP, g.

Die Diskussion fand vor mehr als einem Monat statt, und ich habe wahrscheinlich einige vergessen
Details an dieser Stelle.

IIUC können Sie den WASM-Stack (gemäß Spezifikation) vollständig verwerfen. Ein erweiterbarer und kopierbarer Go-Stack muss noch untersucht werden.

Ja, das ursprüngliche Design, das ich erwähnt habe, verwendet nur den WASM-Stack für
Zwischenprodukte, die in der Berechnung verwendet werden. Alle Daten befinden sich entweder auf dem Go-Heap (linear
Arbeitsspeicher) oder Pseudoregister in lokalen WASM-Variablen.

Ich erwarte nicht, dass die WASM-Spezifikation das Verschieben/Segmentieren und Kopieren von Stapeln enthält.
Es wird selten von Mainstream-Sprachen verwendet, auf die WASM abzielt.

@bradfitz @minux @vibhavp Wie ist der aktuelle Stand von Wasm in Golang? Seit dem 13. März ist nichts passiert! Wird es in Zukunft möglich sein, Golang in Wasm umzuwandeln? gibt es vielleicht eine routenkarte davon?

wenn sich jemand entscheidet, wasm support zu implementieren, kann ich meine zeit für nicht-globale aufgaben anbieten

@SerkanSipahi , niemand arbeitet daran. Dieser Fehler ist als LongTerm gekennzeichnet. Wenn etwas passiert, sehen Sie hier Updates.

Ein guter Fahrplan?

Wir haben DELVE und GDLV zum Debuggen von Golang mit einer GUI. Es funktioniert auch gut auf allen Desktops und Perf ist ausgezeichnet.
https://github.com/derekparker/delve
https://github.com/aarzilli/gdlv

Jetzt basiert GDLV auf NUCULAR, das mit einigen netten Abstraktionen glänzt.
https://github.com/aarzilli/nucular

SO dachte ich, dies wäre eine gute Grundlage, um das zu tun, was hier bereits getan wurde:

Es gibt jetzt auch 5 WASM go-Bibliotheken:
https://github.com/search?l=Go&q=webassembly&ref=simplesearch&type=Repositories&utf8=%E2%9C%93

NaCl wird heruntergefahren - https://blog.chromium.org/2017/05/goodbye-pnacl-hello-webassembly.html
Das sollte also wahrscheinlich bereinigt werden - https://github.com/golang/go/tree/master/misc/nacl

Ich glaube, dass NaCl von verschiedenen Teilen des Go-Ökosystems verwendet wird. Das heißt, es wird nicht nur von Chrome verwendet. Und auf jeden Fall handelt diese Blog-Ankündigung von PNaCl, das, obwohl es eine ähnliche Funktionalität wie NaCl bietet, eigentlich ein völlig anderes Produkt ist, das auf einer anderen Technologie basiert. Daher ist es derzeit verfrüht, die NaCl-Unterstützung von Go zu entfernen.

Egal, ob wir NaCl aus Go entfernen oder nicht, hat nichts damit zu tun, ob wir Unterstützung für Web Assembly hinzufügen.

Ich würde sagen, dass PNaCl nur eine Erweiterung von NaCl ist, um plattformunabhängigen Code bereitzustellen . com/d/topic/native-client-discuss/wgN2ketXybQ/discussion

Ist es möglich, eine Liste der verschiedenen Teile des Go-Ökosystems zu erhalten, in denen NaCl noch verwendet wird?
Wenn Sie es einzeln durchgehen, wird der Übergang zu WebAssembly interessanter.

Ich würde sagen, dass PNaCl nur eine Erweiterung von NaCl ist

Du kannst sagen, was du willst, aber das bedeutet nicht, dass du Recht hast. Sie sind völlig unterschiedliche ISAs, NaCL ist nur die Ziel-ISA (x86/Arm) mit einigen Einschränkungen, während PNaCl eine völlig andere ISA für eine abstrakte Maschine ist.

Go hat PNaCL nie unterstützt, und der Go NaCL-Port war sowieso nie für Chrome geeignet. Es hatte nichts mit Chrome zu tun, es war im Browser nicht nutzbar. Ob Chrome auf NaCL oder PNaCL verzichtet, hat für Go keinerlei Relevanz. Nada, null, keine Relevanz . Wie oft muss das noch gesagt werden? Wenn NaCL vollständig aufgegeben wird, wird Go natürlich irgendwann gezwungen sein, es auch aufzugeben.

Die WebAssembly-Unterstützung in Go hat absolut nichts mit NaCL zu tun. Go kann WebAssembly-Unterstützung erhalten oder nicht. Ob oder wann es eine solche Unterstützung geben könnte, hat keine Relevanz für den Zustand des NaCL-Ports.

Hier ist ein sehr wichtiger Teil des Ökosystems, in dem wir nacl verwenden: https://play.golang.org/p/MfJIq8wb5-

(das serverseitig läuft, nicht nacl-in-a-browser)

Ob Chrome auf NaCL oder PNaCL verzichtet, hat für Go keinerlei Relevanz. Nada, null, keine Relevanz.

Und wer unterstützt dann Sandbox Loader und Toolchain? Es wird aus dem Chrome-Projekt importiert, das auf WebAssembly umgestellt hat. Wäre es nicht ratsam, zu verfolgen und zu sehen, ob Go Playground bereits von der NaCl-Sandbox auf die WebAssembly-Sandbox portiert werden kann? Es kann auch serverseitig ausgeführt werden.

Ich denke, jeder ist dafür, WebAssembly zu unterstützen.

Der Zeitpunkt, um die Abkehr von NaCl zu diskutieren, ist, nachdem WebAssembly vollständig funktioniert hat. Es hat keinen Sinn, vorher darüber zu diskutieren.

@ianlancetaylor , können Sie klarstellen, "nachdem WebAssembly voll funktionsfähig ist"?

Auf den ersten Blick sieht es so aus, als ob webassembly.org sagt: „Die erste Version von WebAssembly hat einen browserübergreifenden Konsens erreicht“ und wasm ist in aktuellen oder zukünftigen Browserversionen von allen Browseranbietern verfügbar.

@vine77 Ich meine, nachdem WebAssembly für Go-Programme voll funktionsfähig ist, funktioniert NaCl heute mindestens so gut.

Was ist also der nächste Test, der bestehen sollte, damit WebAssembly für Go-Programme funktioniert?

@techtonik Ich habe das Gefühl, dass hier einige Verwirrung herrscht. Wenn wir sagen, dass WebAssembly für Go-Programme funktionieren soll, meinen wir damit, dass der Go-Compiler WebAssembly-Code generieren soll, der im Browser ausgeführt werden kann. Wir meinen, dass Sie in der Lage sein sollten, etwas wie GOOS=wasm go build hello.go zu schreiben und ein Programm zu erhalten, das in einem Browser ausgeführt werden kann. Wir sind nicht einmal annähernd in der Nähe davon. Wir haben noch nicht einmal angefangen. Es gibt also keinen „nächsten Test“. Es gibt viel zu tun. Und soweit ich weiß, arbeitet niemand aktiv daran.

@ianlancetaylor
Es gibt 4 Implementierungen für Golang. Eine wirklich beeindruckend. Siehe meinen vorherigen Kommentar für die Links.

Junge, dieser Thread ist wie ein Chevy Chase-Auto, das mit den Kindern auf dem Rücksitz gesehen wird, die schreien: "Sind wir schon da?" :)

@ joeblew99 : Keiner dieser Links kann Go to WebAssembly kompilieren.
Sie sind Dinge wie ein in Go geschriebener WebAssembly -> amd64-Compiler.

Ich hatte Angst, dass du das sagen würdest. Fair genug.
Was wird also für das „Erziehen“ benötigt? Also jeder weiß...
Gopherjs hat irgendwie den gleichen Fehler gemacht, nicht auf der richtigen Ebene in der Compiler-Tool-Chain-Architektur/Code-Generierung zu sein?

Es gibt eine lange Liste. Die meisten haben mit Garbage Collection zu tun, auf die eine oder andere Weise.

  • Generieren Sie WebAssembly-Code im SSA-Back-End. Das Backend wird zum Registrieren von Maschinen verwendet, die Anpassung an die Stack-Maschine von WebAssembly erfordert einige Arbeit.
  • Was ist ein Zeiger? WebAssembly hat keinen Zeigertyp.
  • Wie prüfen wir den Stack? Wir würden dies sicherlich für die Garbage Collection brauchen, aber auch für Panik/Wiederherstellung, Traceback-Druck usw.
  • Wie können wir eine Goroutine unterbrechen/fortsetzen?
  • Wie können wir den Haufen auslegen? WebAssembly bietet im Wesentlichen nur sbrk. Wir brauchen ein allgemeineres Adressraum-Layout. Wo speichern wir Informationen über Spans, ptr/nonptr-Bits usw.?
  • Multithreading. WebAssembly hat im Moment keine Vorstellung von Threads, die wir zum Beispiel für gleichzeitige GC benötigen würden. Wir bräuchten auch Schleusen und vielleicht atomare Operationen.
  • Wie stellen wir Paketen wie os und net den Zugang zur Außenwelt bereit?
  • WebAssembly unterstützt "goto" nicht.

Das ist wahrscheinlich keine vollständige Liste.

Wenn wir sagen, dass WebAssembly für Go-Programme funktionieren soll, meinen wir damit, dass der Go-Compiler WebAssembly-Code generieren soll, der im Browser ausgeführt werden kann.

@ianlancetaylor wäre es einfacher, zuerst Nicht-Web anzusprechen? NaCl wurde auch entwickelt, um zuerst im Browser ausgeführt zu werden, bekam dann aber einen browserunabhängigen Loader, den Go derzeit verwendet. WebAseembly ohne Browser - http://webassembly.org/docs/non-web/ - und es spricht von minimalen Shells zum Testen.

@randall77 ist es möglich, eine umsetzbare Checkliste aus dieser Liste herauszuholen? Wie eine Masterausgabe mit Links zu Ausgaben, die jeden Aspekt im Detail erforschen?

@techtonik wrt non-web: @vibhavp arbeitet daran im Rahmen des GSoC-Praktikums, auf das ich oben in einigen Posts angespielt hatte.
es ist da drüben: https://github.com/go-interpreter/wagon

@techtonik : Ich denke, der richtige Ort für eine solche Checkliste ist ein Antragsdokument zur Unterstützung von wasm. Sobald ein solcher Vorschlag akzeptiert wird und/oder die Leute aktiv daran arbeiten, könnten sie Probleme für individuelle Aufgaben verwenden, sicher. Das ist an dieser Stelle verfrüht - ich kenne niemanden, der aktiv an einem der beiden arbeitet (ein Vorschlag oder Code).

Ich stimme einem Vorschlagsdokument zu.
Alle ich / Widersprüche sind in diesem Thread und müssen einfach zusammengepackt werden, mit einer Roadmap, die das Risiko / Ertrags-Gleichgewicht inszeniert.

Ich würde auch gerne sehen, dass es auch Grafiken anspricht, da es für mich wie ein wunder Daumen herausragt.

Ich bin der Autor von GopherJS , einem Compiler von Go to JavaScript. Ich habe dieses Projekt geschrieben, weil ich fest davon überzeugt bin, dass es Alternativen zur Verwendung von JavaScript im Browser geben sollte, Alternativen wie Go und andere. Ich habe anständige Kenntnisse über Compiler, SSA, Maschinenarchitektur usw., aber mir fehlen wahrscheinlich viele Details, da ich noch kein Compiler-Backend für Maschinencode geschrieben habe. Aus diesem Grund fühle ich mich nicht qualifiziert, ein vollständiges Vorschlagsdokument zu schreiben. Dennoch würde ich gerne ein kritisches Feedback zu meinen Gedanken zu Go und WebAssembly erhalten.

Wenn ich mir WebAssembly anschaue, scheint es mir sehr anders zu sein als die üblichen Maschinencode-Ziele wie x86 oder arm. Beispielsweise ist seine Architektur eine Stapelmaschine anstelle einer Registermaschine. Damit eignet es sich nicht ohne Weiteres als weiteres Target auf der letzten Stufe des Go-Compilers neben x86 & Co. Eine Lösung könnte darin bestehen, es nicht dort abzulegen, sondern stattdessen einen deutlich anderen Ansatz zum Generieren von WebAssembly zu verfolgen. Der Code für diesen Ansatz müsste neben den vorhandenen Compiler-Stufen leben, was überhaupt nicht schön wäre. Man könnte in diesem Szenario sogar einen Fork des Compilers in Betracht ziehen. Kurzum: Ich sehe das nicht.

Es könnte eine Alternative geben: Emulieren Sie, was wir brauchen. Wir können die Stapelmaschine verwenden, um eine Registermaschine zu emulieren, und zwar hoffentlich auf eine vernünftig performante Weise. WebAssembly hat einen linearen Speicher mit Lade- und Speicheranweisungen, was gut ist. Wir würden die call -Anweisung von WebAssembly überhaupt nicht verwenden und stattdessen unseren eigenen Stapelverwaltungs- und Aufrufmechanismus ausführen. Stapel würden auf diesem linearen Speicher leben und von der Go-Laufzeit verwaltet werden. Der Stapelzeiger wäre eine globale Variable. Der gesamte Code würde sich in einer einzigen WebAssembly-Funktion befinden. Die oberste Ebene wäre eine riesige switch-Anweisung (oder das auf br_table basierende Äquivalent von WebAssembly) mit einem Zweig für jede Funktion. Jede Funktion hätte eine andere Switch-Anweisung mit einer Verzweigung pro SSA-Basisblock. Es gibt einige Details, die ich hier weglasse, aber im Großen und Ganzen sieht das für mich nach einer anständigen Registrierungsmaschine aus. Natürlich hängt die Leistung stark davon ab, wie gut WebAssembly diese Konstrukte in tatsächlichen Maschinencode umwandeln kann.

Also sag mir bitte: Bin ich völlig naiv und verrückt? Dann schiebe ich meine Gedanken gerne auf, bis ich mehr erfahren habe. Wenn nicht, kann dies als Ausgangspunkt für ein tatsächliches Vorschlagsdokument dienen. Danke.

Zusätzlich zu all der Arbeit, die auf der Go-Seite erforderlich ist, gibt es einige Dinge, die WebAssembly möglicherweise benötigt, bevor die Go-Laufzeit darauf abzielen kann.

WebAssembly hat noch keine Threads, aber es ist auf der Roadmap und es gibt eine Spezifikation. https://github.com/WebAssembly/threads

In Bezug auf die Garbage Collection scheint es in Zukunft mehrere Optionen zu geben, basierend auf Lin Clarks Vortrag https://youtu.be/HktWin_LPf4?t=28m31s

28:31
So können Sie heute Ihren eigenen Garbage Collector mit Code herunterschicken, wenn Sie möchten, aber es ist
langsam aus einigen Gründen und die Community-Gruppe macht es für WebAssembly-Code möglich
nur mit dem eingebauten GC zu verwenden, der für die Browser hochgradig optimiert ist
daran gearbeitet haben, also wird es schnell laufen und Sie werden diese Integration haben.

Wie bei gomobile gilt es, die Sprachbrücke herauszufinden.

@randall77 erwähnte Threads auch als Voraussetzung für den GC. Ist das wirklich eine harte Anforderung für die erste Version? Parallelität kann auch in einem einzelnen Thread erfolgen.

In Bezug auf die Implementierung von GC glaube ich persönlich nicht daran, dass ein GC alle regiert. Ich würde es vorziehen, wenn Go einen Go-spezifischen GC und Python einen Python-spezifischen GC hätte. Indem wir unseren eigenen Heap und Stacks vollständig im linearen Speicher von WebAssembly verwalten, sollten wir in der Lage sein, den GC zu verwenden, den Go bereits hat, soweit ich das derzeit sehen kann.

@neelance Ja, mehrere echte WebAssembly-Threads sind ein nettes Extra, keine strikte Anforderung.

Der GC-Vorschlag für WebAssembly ist noch in Arbeit. Interessierte können sich hier beteiligen:

https://github.com/WebAssembly/gc

@neelance , ich weiß nichts über Compiler, SSA, Maschinenarchitektur usw. Können Sie bitte sagen, wie sich das, was Sie beschrieben haben, auf die Binärgröße auswirken würde? Wenn ich das richtig verstehe, war die Größeneffizienz eines der übergeordneten Ziele von WebAssembly . Es sollte auch eine der Prioritäten für diesen Go->WebAssembly-Compiler sein, richtig?

@alxkchr Meine Erfahrung ist, dass die Wiederholung aufgrund von Code-Gen-Boilerplates durch die Anwendung von gzip stark kompensiert werden kann. Dennoch ist mein Vorschlag nicht die effizienteste Lösung in Bezug auf die Binärgröße. Dennoch ist eine Lösung, die in angemessener Zeit implementiert werden kann, besser als keine Lösung, oder? ;-) Auch für mich persönlich steht Binärgröße nicht an erster Stelle.

zu Ihrer Information: Ich habe damit begonnen, dies umzusetzen.

@neelance beste Nachricht aller Zeiten :) hältst du dich an die Spezifikation? (Ich hoffe)

Die Go-Spezifikation? Es ist ein neues Backend/Ziel für den normalen Go-Compiler, also ist die Spezifikation bereits drin. ;)

ich meine wasm spec :)

@neelance

zu Ihrer Information: Ich habe damit begonnen, dies umzusetzen.

Können Sie bitte mitteilen, welcher Ansatz zur Adressierung verwendet wird?

Unsere aktuelle Schlussfolgerung ist, dass es keinen effizienten Weg zur Implementierung gibt
setjmp/longjmp-Funktionalität derzeit, daher ist es kein praktikables Ziel
eines GC-Ports. Wir müssen warten, bis es zum echten Stapelabbau kommt
Unterstützung der Ausnahmebehandlung.

(https://github.com/golang/go/issues/18892#issuecomment-276858667)

@neelance : Ich weiß, es ist noch früh, aber ich denke, es wäre klüger, den Wasm GOARCH wasm32 zu nennen (dasselbe gilt für die Pakete).

@sbinet Es lohnt sich zu bedenken, dass die ARM-Architekturen / -Pakete arm und arm64 (ähnlich mips und mips64 ) und nicht arm32 und arm64 . Allerdings weiß ich nicht, ob das als gutes oder schlechtes Beispiel zu werten ist.

@SerkanSipahi Ich ziele zunächst auf V8 (nodejs/chrome) und verwende https://webassembly.github.io/spec/ als Dokumentation darüber, was zu tun ist.

@stuart-warren Ja, mein WIP befindet sich in diesem Zweig. Versuchen Sie jedoch noch nicht, es zu verwenden, es kann im Moment nicht einfach erstellt werden und ist voll von kopiertem Code und Stubs/Hacks. Ich werde es hier ankündigen, wenn es einen Alpha-Status erreicht.

@cznic Wie oben geschrieben, verwende ich überhaupt nicht die call -Anweisung von wasm, ich verwalte meinen eigenen Stack im linearen Speicher. Somit kann setjmp/longjmp implementiert werden.

@sbinet Eigentlich wird es eine 64-Bit-Architektur sein, da wasm 64-Bit-Operationen hat.

@neelance nicht ganz. Die WebAssembly-Spezifikation unterstützt derzeit nur 32-Bit-Adressräume, eine wasm64 -Spezifikation ist für später geplant .

Interessant, danke für den Link. Vielleicht möchten wir später darauf zurückkommen. Derzeit speichere ich alles in 64-Bit-Variablen, also haben int , uint und uintptr alle eine Größe von 64 Bit. Allerdings werden nur die ersten 32 Bits zur Adressierung des Speichers verwendet. Das ist zunächst einfacher umzusetzen.

Es klingt dann wie wasm64p32 (um der Nacl-Benennung zu folgen) oder so
ähnlich.

Am 4. November 2017 um 5:28 Uhr schrieb „Richard Musiol“ [email protected] :

Interessant, danke für den Link. Vielleicht möchten wir später darauf zurückkommen.
Derzeit speichere ich alles in 64-Bit-Variablen, also int, uint und uintptr
alle haben eine Größe von 64 Bit. Allerdings werden dafür nur die ersten 32 Bit verwendet
Speicher adressieren. Das ist zunächst einfacher umzusetzen.


Sie erhalten dies, weil Sie diesen Thread abonniert haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/golang/go/issues/18892#issuecomment-341889653 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/AAgwpPTbfHRmoYNXLQfcPMVnARxb0UGrks5szEpjgaJpZM4L0o7D
.

Es klingt dann wie wasm64p32 (um der Nacl-Benennung zu folgen) oder so
ähnlich.

Ich glaube nicht, dass es sinnvoll ist, zwei Nummern zu haben, da es nur eine Architektur geben wird (mit einer Auswahl an Adressraumgrößen). Von webassembly.org :

wasm32 und wasm64 sind beides nur Modi von WebAssembly, die durch ein Flag in einem Modulheader ausgewählt werden und keine semantischen Unterschiede implizieren, abgesehen davon, wie linearer Speicher behandelt wird.

Ich glaube nicht, dass es sinnvoll ist, zwei Nummern zu haben, da es nur eine Architektur geben wird (mit einer Auswahl an Adressraumgrößen). Von webassembly.org:

wasm32 und wasm64 sind beides nur Modi von WebAssembly, die durch ein Flag in einem Modulheader ausgewählt werden und keine semantischen Unterschiede implizieren, abgesehen davon, wie linearer Speicher behandelt wird.

Das ist eine ambitionierte Aussage. Es könnte sich als wahr herausstellen, aber die WebAssembly CG / WG hat wasm64 nicht ausreichend untersucht, um mich darauf verlassen zu können, dass die Aussage korrekt ist.

Lassen wir @neelance arbeiten. Namen können später leicht geändert werden.

Ich weiß, dass Go direkt zu Maschinenanweisungen kompiliert wird (AFAIK), aber ich frage mich, ob jemand jemals Go nach C kompiliert hat. Es wäre interessant, Go --> C --> wasm zu versuchen (wenn auch nicht sehr effizient).

@TomerHeber es kann in Form einer Übersetzung nach C++ möglich sein, nicht als Kompilierung, aber wahrscheinlich wird dies mehr Arbeit sein als die Kompilierung von wasm selbst

Hallo allerseits. Hier ein Update zu meiner Arbeit: Ich mache sehr gute Fortschritte, was vor allem der großartigen Arbeit des Go-Teams und der Mitwirkenden zu verdanken ist. Der größte Teil des Codes wird von Architekturen/Plattformen gemeinsam genutzt, sodass nicht so viel implementiert werden musste, wie ich erwartet hatte.

Hier ist eine Liste von Dingen, die bereits gut funktionieren:

  • Ausführen des generierten Wasm-Codes in Browsern und in Node.js
  • grundlegende Operationen, Konvertierungen usw.
  • Schnittstellen
  • Goroutinen & Kanäle
  • aufschieben/Panik/Rettung
  • Lesen von Dateien von der Festplatte bei Verwendung von Node.js
  • Tests der folgenden Pakete werden bestanden: bytes, container/heap, container/list, container/ring, encoding/ascii85, encoding/asn1, encoding/base32, encoding/binary, encoding/csv, encoding/hex, errors, flag, hash/adler32, hash/crc32, hash/crc64, hash/fnv, html, image, image/color, index/suffixarray, math, math/bits, path, sort, strconv, strings, text/scanner, text/tabwriter, unicode, unicode/utf8, unicode/utf16

Einige Dinge, die noch bearbeitet werden müssen:

  • Betrachtung
  • den Stapel von Goroutinen wachsen lassen
  • Müllabfuhr
  • Leistungsoptimierungen
  • wasm-Dateigrößenoptimierungen
  • eine schöne JS-Interop-Schicht
  • viele andere Probleme, um mehr Pakettests zu bestehen

Ich freue mich sehr über die Fortschritte in anderthalb Monaten und nur in meiner Freizeit. Ich denke, es besteht eine gute Chance, dass wir dies in Go 1.11 einbauen könnten. Erwarten Sie mein nächstes Update im Januar, da ich im Urlaub bin und dann sind da die Feiertage.

Können einige dieser Aufgaben parallelisiert werden? Einige Bits scheinen für Urlaubshacks interessant zu sein.

Schauen Sie sich das gerne an und erstellen Sie eine PR auf meiner Gabel. Sie können mich auch auf Gophers Slack finden.

Ein Bereich der Untersuchung könnte die Optimierung der Nutzung des Stacks sein. Im Moment weist die Registerzuweisungsphase Register (lokale Variablen in wasm) für jede Operation zu. get_local und set_local werden immer vor und nach jeder Operation verwendet. Dies ist unnötig, wenn der Wert einfach auf dem Stapel bleiben könnte, um von einer späteren Operation verwendet zu werden. Ich schlage vor, ein Pseudoregister REG_STACK hinzuzufügen und den Befehlsgenerator get_local und set_local überspringen zu lassen, wenn dieses Register verwendet wird. Dann sorgen Sie dafür, dass regalloc dieses Register gegebenenfalls verwendet.

Betreff:

eine schöne JS-Interop-Schicht

Gibt es derzeit eine vernünftige Möglichkeit, dies für Wasm zu implementieren? Ich dachte, Dom/js interop wäre ein Ausweg mit wasm noch. Wenn das möglich wäre, wäre das riesig!

Sie können Funktionen importieren und exportieren, die float64 - und int32 -Argumente haben können, und Sie haben den gemeinsam genutzten linearen Speicher. Alles andere kann darauf aufgebaut werden. Nur Garbage Collection wäre nicht so schön.

(Ich habe versucht, dies in Ihrem Repo (@neelance) zu posten, aber ich konnte nicht herausfinden, wie man Probleme postet ...)

Wäre es möglich, die wabt -Toolchain zu verwenden, anstatt js.foo aufzurufen/zu importieren?
Ich fand es einfacher, mit wabt zu interagieren als mit einer vollständigen nodejs -Installation :)

(Ich versuche auch, ein einfaches main.go -Programm zu interpretieren, übersetzt in a.wasm hier: go-interpreter/wagon#36...)

Ich habe Probleme auf meinem Fork aktiviert, zögern Sie nicht, dort zu posten.

Ich verstehe deine Frage nicht wirklich. Redest du von wasm-interp ? Etwas muss den Wasm-Bytecode kompilieren und ausführen, und Sie benötigen eine JS-Umgebung, um mit dem Rest des Systems zu interagieren, z. B. zum Drucken auf der Konsole.

Das ist toll. Für diejenigen, die versuchen möchten, Go to wasm zu kompilieren und auszuführen -

  1. Erstellen Sie ein einfaches Hallo-Welt-Programm, das auf der Konsole gedruckt wird.
  2. GOOS=js GOARCH=wasm ./bin/go build -o out.wasm wasm.go
  3. ./misc/wasm/go_js_wasm_exec out.wasm

Genießen !

Wenn Sie go_js_wasm_exec in Ihren PATH einbinden, können Sie sogar go run verwenden. ;-)

Hey Leute, wie ist die Garbage-Collection-Situation mit Go for WASM? Wir begannen darüber zu sprechen, Crystal zu übernehmen, und es scheint, dass Crystal wahrscheinlich die gleichen Probleme hat, die Go derzeit mit GC hat. Gibt es eine Möglichkeit, mit der WebAssembly-Arbeitsgruppe in dieser Situation zusammenzuarbeiten oder ihr zu helfen?

Bitte zögern Sie nicht, sich an dem oben genannten Thread zu beteiligen oder uns mitzuteilen, wo wir uns vielleicht unterhalten / möglicherweise an diesem Problem zusammenarbeiten könnten.

Es kann sein, dass der Opal-Pfad vorerst der vernünftigere Ansatz ist, bis WASM in diesem Bereich reift, aber es wäre gut, dies sicher zu wissen, bevor Sie diesen Pfad einschlagen.

Hey Leute, ich wollte teilen, woran ich in den letzten Monaten gearbeitet habe, da ich denke, dass ein Großteil des zugrunde liegenden Codes relevant ist: https://github.com/matthewmueller/joy

Ich ziele gerade auf JS (ES3) ab, aber der Compiler implementiert ein Abhängigkeitsdiagramm für alle Deklarationen (Funktionen, Variablen usw.). Anschließend sortiert es den Graphen und übersetzt nur die Deklarationen, die im Programm verwendet werden.

Ich glaube nicht, dass es zu schwierig wäre, dieses Diagramm zu verwenden und auf WebAssembly abzuzielen. Ich bin eifrig zu helfen und mitzuarbeiten, wo immer ich kann.

Für weitere Informationen hier einige relevante Links:

In Bezug auf das obige GC-Problem für Crystal könnte dies auch für Go gelten, beachten Sie die Bemerkungen von @kripken und die folgende Diskussion hier: https://github.com/WebAssembly/binaryen/issues/1312#issuecomment -348409211

Ich hoffe, alle hatten schöne Feiertage. Hier das versprochene Update:

Seit meinem letzten Update habe ich es geschafft, Reflection, Stack-Growing und die Garbage Collection zum Laufen zu bringen. Weitere Verbesserungen haben es soweit gebracht, dass die Tests von 104 von 136 stdlib-Paketen nun bestanden sind. Außerdem sind viele der Compiler-Tests grün. Gute Fortschritte!

Bitte beachten Sie, dass ich mich derzeit auf die Unterstützung und Korrektheit von Funktionen konzentriere. Ich habe noch keine Optimierungen für Leistung oder Ausgabegröße vorgenommen.

Ich begrüße das Experiment (und @neelance ty so sehr für GopherJS für die überlegenen Goroutinen im Vergleich zu Promise , Sie haben mich wahrscheinlich vor C++ gerettet !), Daher ist das Folgende nur ein Versuch, potenziell nützliche Informationen hinzuzufügen und vielleicht sogar, um das Bewusstsein für die Inkongruenz zwischen Go und einem WASM-Ziel zu schärfen. Möglicherweise auch, um das Problem für einige Leser zu klären. Auch weil ich einen geeigneten Platz zum Ablegen des folgenden @rossberg- Zitats suchte, das ich fand, als ich unabhängig darüber nachdachte, wie man so etwas wie Gorountines für WASM kompiliert.

@neelance antwortete :

@cznic antwortete :

@neelance schrieb :

Wir würden die call -Anweisung von WebAssembly überhaupt nicht verwenden und stattdessen unseren eigenen Stapelverwaltungs- und Aufrufmechanismus ausführen. Stapel würden auf diesem linearen Speicher leben und von der Go-Laufzeit verwaltet werden. Der Stapelzeiger wäre eine globale Variable. Der gesamte Code würde sich in einer einzigen WebAssembly-Funktion befinden. Die oberste Ebene wäre eine riesige switch-Anweisung (oder das auf br_table basierende Äquivalent von WebAssembly) mit einem Zweig für jede Funktion. Jede Funktion hätte eine andere Switch-Anweisung mit einer Verzweigung pro SSA-Basisblock.

Können Sie bitte mitteilen, welcher Ansatz verwendet wird, um Folgendes anzugehen:

@minux schrieb :

Unsere aktuelle Schlussfolgerung ist, dass es keinen effizienten Weg zur Implementierung gibt
setjmp/longjmp-Funktionalität derzeit, daher ist es kein praktikables Ziel
eines GC-Ports. Wir müssen warten, bis es zum echten Stapelabbau kommt
Unterstützung der Ausnahmebehandlung.

@cznic Wie oben geschrieben, verwende ich überhaupt nicht die call -Anweisung von wasm, ich verwalte meinen eigenen Stack im linearen Speicher. Somit kann setjmp/longjmp implementiert werden.

Laut dem „Co-Designer“ und „Spezifikationsautor“ von WASM haben die Einschränkungen von call , die es für Go ungeeignet machen, etwas mit Sicherheit zu tun:

@rossberg schrieb :

Sie können den Aufrufstapel nicht einfach "ersetzen", da es keine Möglichkeit gibt, Rücksendeadressen (*) zu verifizieren. Sie können jedoch bei Bedarf einen Schattenstapel für Ihre lokalen Variablen im linearen Speicher implementieren.

Tatsächlich stellt WebAssembly derzeit überhaupt keine Vorstellung von eingebautem "Stack" zur Verfügung. Wie bei vielen anderen Designentscheidungen ist das wichtig: Da Wasm im Web läuft, muss es „sicher“ sein. Deshalb ist es typisiert, hat kein undefiniertes Verhalten, Code ist vom Speicher getrennt (und nicht adressierbar), Umwandlungen von Funktionstypen werden überprüft usw. Ein explizites Funktionskonzept ermöglicht auch andere Vorteile, wie z. B. eine effektive Registerzuordnung, parallel oder faul Kompilierung, nützliche Debug-Tools usw.

Der Kontrollfluss ist in der Tat halbstrukturiert: Verzweigungen sind wirklich nur Unterbrechungen und Fortsetzungen, sodass Sie keinen irreduziblen Kontrollfluss konstruieren können. Das ist auch ein Feature.

[…]

(*) Sie könnten vermutlich explizite Rücksprungadressen mit Indizes in einen riesigen Tabellensprung emulieren, indem Sie Ihr gesamtes Programm in eine einzige Schleifenfunktion kompilieren. Aber das wäre wahrscheinlich ziemlich langsam und würde einen Großteil des WebAssembly-Ökosystems zunichte machen .

Die Leistung und Interoperabilität mit dem WASM-Ökosystem dessen, was @neelance versucht, wird also wahrscheinlich suboptimal sein?

Unter Berufung auf die Fähigkeit von @neelance, die Leistung von GopherJS zu optimieren.

Ich weiß nicht, was Sie mit "Interoperabilität mit dem WASM-Ökosystem" meinen, daher kann ich dazu nichts sagen. Zur Leistung kann ich folgendes sagen:

Ja, der aktuelle Ansatz ist nicht der optimalste Weg, um den Kontrollfluss in WebAssembly auszudrücken, aber er funktioniert heute . Vielleicht wird es in Zukunft möglich sein, die call -Anweisung von WebAssembly mehr zu verwenden, aber dafür müsste WebAssembly ein paar weitere Funktionen hinzufügen und es würde viel mehr Arbeit auf der Go-Seite erfordern, um damit kompatibel zu sein. Ich hätte lieber etwas mit 80% der Leistung, das tatsächlich funktioniert, als etwas, das 100% hat, aber nur hypothetisch ist. ;-)

Wenn Sie an weiteren technischen Details interessiert sind, sprechen Sie mit mir auf #webassembly unter https://invite.slack.golangbridge.org/.

Ich weiß nicht, was Sie mit "Interoperabilität mit dem WASM-Ökosystem" meinen, daher kann ich dazu nichts sagen.

Vielleicht bezieht sich @rossberg mit _„einen Großteil des WebAssembly-Ökosystems besiegen“_ auf die Interoperabilität mit Tools und anderen Sprachen im Ökosystem, die call und den geschützten Call-Stack nicht umgehen, indem sie im Wesentlichen Ihren emulieren eigene Fortsetzungen mit switch -Tabellen?

aber dafür müsste WebAssembly noch ein paar Features hinzufügen

Ich hoffe, dass WASM Sprachen mit Goroutinen (grüne Fäden) besser aufnehmen würde, da Afaics dem Stack-Unwinding-JavaScript- Promise -Modell unbestreitbar überlegen sind.

Ich hätte lieber etwas mit 80% der Leistung, das tatsächlich funktioniert, als etwas, das 100% hat, aber nur hypothetisch ist. ;-)

Oh, ich stimme vollkommen zu, weshalb ich dafür gesorgt habe, dass ich meinem vorherigen Beitrag meinen Applaus für Ihre produktiven Bemühungen vorangestellt habe.

Je beliebter im Web/WASM wir Go oder andere Sprachen mit grünen Fäden machen können, desto größer ist vielleicht die Chance, dass wir bessere WASM-Primitive (z. B. analog zu gccs -fsplit-stack ?) für eine bessere Leistung bekommen .

Wenn Ihre Implementierung wirklich 80 % der optimalen Leistung innerhalb der aktuellen Einschränkungen von WASM erreicht, werde ich angenehm überrascht sein. Wenn das Leistungsergebnis übermäßig schlecht ist, kann dies die Demonstration der Popularität grüner Threads im Vergleich zum Callback-basierten Modell Promise von JavaScript einschränken (das Potenzial der Ironie, „einen Großteil des WebAssembly-Ökosystems zu besiegen“, wenn wir davon ausgehen, dass dies der Fall ist Design wurde von einer Priorität auf die Optimierung von JavaScript vorangetrieben :-) .

Beachten Sie auch, dass ich erwäge (noch keine feste Entscheidung), Typklassen-Generika als Transpiler zu Go hinzuzufügen (und meine Analyse des Generika-Vorschlags für Go 2 bereitzustellen), also bin ich möglicherweise auch daran beteiligt, meinen Teil dazu beizutragen, zu versuchen, zu wachsen Popularität.

@shelby3 Bitte hören Sie auf, Formatierungen zu verwenden, die Ihren Text so klein machen, dass er nicht lesbar ist. Wenn Sie der Meinung sind, dass es den Leuten nicht wert ist, etwas zu lesen, schreiben Sie es erst gar nicht. Wenn Sie es unlesbar machen, ohne einen Hinweis darauf zu geben, was verborgen ist, verbringen die Leser zweimal (oder mehr) Zeit damit, es zu entschlüsseln. Ich denke, es ist das Gegenteil Ihrer ursprünglichen Absicht.

@shelby3 Ich habe Ihre Beiträge bearbeitet, um die Verwendung der kleinen Textformatierung zu beenden. Bitte hör auf damit.

Änderung https://golang.org/cl/102835 erwähnt dieses Problem: go/build, cmd/dist: add js/wasm architecture

Änderung https://golang.org/cl/103255 erwähnt dieses Problem: wasm: add scripts for running WebAssembly binaries

Änderung https://golang.org/cl/103256 erwähnt dieses Problem: cmd/compile: add SSA config options noAvg and noHmul

Änderung https://golang.org/cl/103275 erwähnt dieses Problem: cmd/compile/internal/gc: factor out beginning of SSAGenState.Call

Änderung https://golang.org/cl/103295 erwähnt dieses Problem: cmd/compile: add wasm architecture

Änderung https://golang.org/cl/103535 erwähnt dieses Problem: cmd/compile: wasm stack optimization

Änderung https://golang.org/cl/103795 erwähnt dieses Problem: cmd/link: add wasm architecture

Änderung https://golang.org/cl/103877 erwähnt dieses Problem: runtime: add js/wasm architecture

Änderung https://golang.org/cl/103915 erwähnt dieses Problem: internal/bytealg: add wasm architecture

Ok, sieht so aus, als würden viele CLs vorbeifliegen.
Wie steht es um die Portierungsrichtlinie: https://github.com/golang/go/wiki/PortingPolicy ?
Insbesondere, wie werden die Bauherren aussehen?
Ich nehme an, @neelance , dass Sie sich für die Wartung des Ports anmelden?
(Ich entschuldige mich, wenn einer der CLs das alles buchstabiert, ich habe sie nicht alle gelesen.)

Ja, ich werde den Port pflegen. @bradfitz prüft derzeit die Einrichtung des Builders.

Änderung https://golang.org/cl/106995 erwähnt dieses Problem: sync/atomic: add wasm architecture

Änderung https://golang.org/cl/106996 erwähnt dieses Problem: math: add wasm architecture

Änderung https://golang.org/cl/106997 erwähnt dieses Problem: time: add wasm architecture

Änderung https://golang.org/cl/106998 erwähnt dieses Problem: mime: add wasm architecture

Änderung https://golang.org/cl/109195 erwähnt dieses Problem: syscall/js: add package

Änderung https://golang.org/cl/109976 erwähnt dieses Problem: syscall: enable some nacl code to be shared with js/wasm

Änderung https://golang.org/cl/109977 erwähnt dieses Problem: os: add js/wasm architecture

Änderung https://golang.org/cl/109995 erwähnt dieses Problem: net: add js/wasm architecture

Änderung https://golang.org/cl/110095 erwähnt dieses Problem: crypto: add js/wasm architecture

Änderung https://golang.org/cl/110096 erwähnt dieses Problem: all: skip unsupported tests for js/wasm

Änderung https://golang.org/cl/112736 erwähnt dieses Problem: env/js-wasm, dashboard: add start of a js-wasm builder

Änderung https://golang.org/cl/113515 erwähnt dieses Problem: misc/wasm: make wasm_exec.js more flexible

Nachdem ich die Webassembly-Architektur für Go document gelesen habe, speziell für die JavaScript-Syscall-Implementierung, die auf dem 'fs'-Modul von Node aufbaut und für die Browserseite der Dinge weitgehend nicht implementiert ist, frage ich mich, ob wir versuchen könnten oder wollen, diese mit zu implementieren die _neuen_ Browser-APIs? Insbesondere scheint die FileSystem-API -Spezifikation zumindest einige der Systemaufrufe unterstützen zu können. (FileSystem ist immer noch ein Editor's Draft und wird nur in FireFox, Chrome und Opera implementiert. Außerdem ist es den beiden letzteren mit dem Präfix "webkit-" versehen.)
Ich könnte versuchen, einen Proof of Concept zu erstellen, wenn Sie denken, dass dies ein anständiger Ansatz sein könnte.

Änderung https://golang.org/cl/114197 erwähnt dieses Problem: runtime, sycall/js: add support for callbacks from JavaScript

Hallo zusammen, ich liebe die Arbeit von @neelance , und ich habe mich gefragt, ob es mit dieser WASM-Implementierung (sagen wir, der ersten Version davon) möglich sein wird, auch cgo zu verwenden. C-Code einbetten, zu GO kompilieren, zu WASM kompilieren. Das wäre eine verdammte Superkraft. Ihr macht alle einen tollen Job. Fantastisch.

@cmaster11 Freut mich zu hören, dass es dir gefällt. :) Zu Ihrer Frage: cgo kompiliert C to Go nicht, sondern kompiliert beide Sprachen mit ihren jeweiligen Compilern zu Maschinencode und führt dann die Ergebnisse zu einer einzigen Binärdatei zusammen. Sie können emscripten bereits verwenden, um C-Code für WebAssembly zu kompilieren. Theoretisch sollte es möglich sein, beide WebAssembly-Binärdateien zur Laufzeit zu laden und sie interagieren zu lassen. Ich halte es jedoch für unwahrscheinlich, dass das Go-Projekt in naher Zukunft Zeit darauf verwenden wird, diesen Anwendungsfall zu ermöglichen.

anscheinend hauptsächlich Millennials

@shelby3 Ich bin wahrscheinlich älter als du und habe dich abgelehnt. Das Problem hier ist einfach Ihre Unfähigkeit zu kommunizieren.

Es geht nicht um Macht. @andybons hat dir tatsächlich einen Gefallen getan, indem er deinen Beitrag bearbeitet hat, damit er von anderen gelesen werden kann.

js/wasm-Unterstützung ohne webidl impliziert, dass wir nicht viel mit anderen Sprachen innerhalb des Webbrowsers interagieren können. Die wasm-Architektur schien nichts über webidl zu erwähnen.

Ich habe mir das Python-Tool emscripten webidl genau angesehen, wenn es wie folgt auf die C++-Klasse Foo angewendet wird.
Ich würde gerne einen Golang-Ententyp sehen, der über webidl auf die gleiche Weise wie die Foo-Klasse verfügbar gemacht wird.
Dieser Grund wäre, mit anderen wasm-Modulen zusammenzuarbeiten, die gleichzeitig geladen werden, aber wir brauchen die verfügbaren IDLs, um ihre Marshalling-Stubs einbeziehen und aufrufen zu können. Andernfalls benötigen wir eine Art Objektbetrachter, um festzustellen, welche Anrufsignaturen in den verschiedenen WASM-Dateien verfügbar sind.

python /usr/lib/emscripten/tools/webidl_binder.py Foo.idl glue
This generates:
glue.cpp
glue.js
WebIDLGrammar.pkl

emcc -v Foo.cpp my_glue_wrapper.cpp --post-js glue.js -o output.js
This generates:
output.js
output.wasm

emrun --list_browsers
emrun --browser chrome handcrafted_Foo.html 
emrun --browser firefox handcrafted_Foo.html 
firefox handcrafted_Foo.html &
chrome handcrafted_Foo.html &

$ cat Foo.h

#ifndef FOO_H
#define FOO_H (1)

class Foo {
public:
  int getVal();
  void setVal(int v);
 private:
  int nValue;
};

#endif

$ cat Foo.cpp

#include "Foo.h"

int Foo::getVal() {
  return nValue;
}

void Foo::setVal(int v) {
  nValue = v;
}

$ cat my_glue_wrapper.cpp

#include "Foo.h"
#include "glue.cpp"

$ cat Foo.idl

interface Foo {
        void Foo();
        long getVal();
        void setVal(long v);
};

$ cat handcrafted_Foo.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>WebAssembly Sample</title>
  </head>

  <body>
    <h1>Web Assembly</h1>

    <div class="output">
        <pre id="log"></pre>
    </div>

    <script src="output.js"></script>
    <script>      
      "use strict";


    function log() {
        document.querySelector('#log').textContent += Array.prototype.join.call(arguments, '') + '\n';
    }

    Module.onRuntimeInitialized = _ => {
      log(`blah `);
      var f = new Module.Foo();
      f.setVal(200);
      alert(f.getVal());
      log(`blah `);
    };

    </script>

  </body>
</html>

@omac777 , die Interoperabilität mit anderen Sprachen ist kein Ziel für die anfängliche WebAssembly-Unterstützung von Go 1.11.

OK. Ich kann verstehen, dass webidl kein kurzfristiges Ziel ist, aber ich habe Fragen dazu, wie man die Ausgabe von wasm nützlich macht. Gehen wir zunächst zurück zu der obigen Foo-Klasse, die oben für die Verwendung mit emscripten c++ zusammen mit ihrer IDL definiert wurde. Angenommen, ich habe einen Golang-Ententyp erstellt, der dazu passt. Angenommen, ich exportiere diese Funktionen als C-Funktionen, damit sie von den C++ Foo SetVal- und GetVal-Implementierungen aufgerufen werden können. Ich weiß, dass es dadurch langsamer wäre, aber das langfristige Ziel wäre es, die gesamte Implementierung innerhalb von Go zu erstellen.

Wie erstelle ich foo.go.wasm.a's und foo.go.wasm.so's? Braucht jede foo.wasm ihre eigene foo.go.js?
Wenn eine Bibliothek voller verschiedener Foos generiert würde, würde dann auch ein otherfoos.go.a.js generiert werden?

Wie verknüpfe ich go.wasm.a und go.wasm.so mit der generierten emcc output.wasm wie angegeben in:
emcc -v Foo.cpp my_glue_wrapper.cpp --post-js glue.js -o output.js foo.go.wasm otherfoos.go.wasm.a

So verknüpfen Sie beispielsweise SDL-Funktionen, die EMCC von Wasm in Go unterstützt.

Wann wird die Unterstützung für vollständige Goroutinen, MAXCPUCores, Kanäle für Wasm erscheinen?
Danke noch einmal.

@omac777 , was für Go 1.11 gilt, ist Folgendes:

Go-Code wird in ein WebAssembly-Modul kompiliert und in einem Browser ausgeführt, und wir können zwischen JavaScript hin und her rufen.

Ignorieren Sie alles über *.a- oder *.so-Dateien oder Interoperabilität mit C oder GCC oder emcc oder SDL. Nichts davon ist im Umfang und wird nicht funktionieren.

Wann wird die Unterstützung für vollständige Goroutinen, MAXCPUCores, Kanäle für Wasm erscheinen?

Es unterstützt vollständig Goroutinen und Kanäle (das ist Teil von Go und erforderlich). WebAssembly unterstützt nur einen einzelnen Kern, wenn Sie das mit MAXCPUCores meinen. Dies ist keine Einschränkung der WebAssembly-Unterstützung von Go oder Go.

Sie sagen also, ich werde so etwas in absehbarer Zeit nicht sehen?
GOARCH=wasm GOOS=js go build -o awesome.wasm.so -buildmode=c-shared foo.go

Wenn wir also Webbrowser mit 4 Kernen oder 20 Kernen haben, wird der von go generierte Wasm nur einen dieser Kerne im Webbrowser verwenden? Ich verstehe nicht, wie Sie angeben, dass es sich nicht um eine Einschränkung der Go- oder Go-Webassembly-Unterstützung handelt. Wollen Sie damit sagen, dass es sich um eine Einschränkung der WEBASSEMBLY.org-Spezifikation selbst handelt?

@omac777 - Ja, ich glaube, es ist derzeit eine Einschränkung von WebAssembly selbst, nicht der Go-Implementierung.

@omac777 Die Multithreading-Unterstützung in WASM ist noch in Arbeit und es wird eine Weile dauern, bis sie in Browsern veröffentlicht wird.

https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md

Sie sagen also, ich werde so etwas in absehbarer Zeit nicht sehen?
GOARCH=wasm GOOS=js go build -o awesome.wasm.so -buildmode=c-shared foo.go

Wahrscheinlich in Go 1.12.

Für Go, das C/C++ aufruft, denke ich, dass es wahrscheinlich möglich ist, C-Funktionen mit JavaScript zu umschließen und dann den JavaScript-Wrapper von Go mit Go 1.11 aufzurufen.

Ich weiß, dass dies (vielleicht) nicht Teil des Threads ist, aber gibt es Dokumentationen / Tutorials zur Verwendung von WebAssembly (Kompilieren usw.) in go v1.11?

@SerkanSipahi , noch nicht. Aber es wird Dokumente vor der Veröffentlichung geben.

@SerkanSipahi Ich habe die Schritte, die ich unternommen habe, um es zum Laufen zu bringen, unter https://blog.lazyhacker.com/2018/05/webassembly-wasm-with-go.html aufgeschrieben.

Es gibt auch diesen Beitrag, der immer noch relevant ist:
https://blog.gopheracademy.com/advent-2017/go-wasm/

Mir ist aufgefallen, dass wir (IIRC) nicht genau die Zuordnung (noch den Mechanismus) für das angegeben haben, was in den export -Abschnitt eines Wasm-Moduls geht.

Ich habe #25612 eingereicht.

Unter Verwendung des wasm-Targets klären/dokumentieren Sie bitte von go how to:
-Verwenden Sie go, um eine go-Funktion nach und von wasm zu exportieren/importieren, damit andere Sprachen verwendet werden können.
-Link sdl2/webgl/qt zu einer Golang-Binärdatei
- Fangen Sie alle sdl2/webgl/qt-Ereignisse ab
- Geben Sie die CPU-Zeit mit einem Schlaf vorübergehend an das Betriebssystem zurück, wenn wir in einer Schleife sind. zum Beispiel
in emscripten emscripten_sleep(10)

Die Datei output.html aus dem Go-Tool scheint sowohl mit Firefox als auch mit Chrome nicht konsistent erfolgreich zu sein, selbst wenn eine erfolgreiche Ausgabe.html erstellt wurde. Es sollte mehr getan werden, um sicherzustellen, dass output.html funktioniert. bevor es als Erfolg präsentiert wird.

@ omac777 , das meiste davon haben wir oben besprochen. Aber für andere nur einschalten:

Unter Verwendung des wasm-Targets klären/dokumentieren Sie bitte von go how to:
-Verwenden Sie go, um eine go-Funktion nach und von wasm zu exportieren/importieren, damit andere Sprachen verwendet werden können.
-Link sdl2/webgl/qt zu einer Golang-Binärdatei
- Fangen Sie alle sdl2/webgl/qt-Ereignisse ab

Wie oben erwähnt, ist nichts davon im Umfang von Go 1.11 enthalten. Es wird nicht unterstützt, dokumentiert oder wahrscheinlich sogar möglich.

- Geben Sie die CPU-Zeit mit einem Schlaf vorübergehend an das Betriebssystem zurück, wenn wir in einer Schleife sind. zum Beispiel

@neelance hat Rückrufe und Interop zwischen JS und dem Go-Scheduler funktioniert, also sollten normale time.Sleep und Freunde wie erwartet funktionieren.

Ich verstehe, dass Go 1.11 keine davon haben wird, aber wie weit/lange wird eines der oben genannten für Go in Betracht gezogen. Es gibt Leute, die qt gerne sauber in go integriert sehen würden, und derzeit ist die Situation so, dass wir uns für dieses Therecipe/qt auf einen Drittanbieter verlassen, was alles gut ist, aber es gibt Einschränkungen (derzeit kein Wasm-QT und keine qt-64-Bit-Arm-Ziele unterstützt). autocad bietet eine Webassembly-Lösung für Windows und Macos mit Emscripten, C++ und React. Ich habe immer noch das Gefühl, dass Golang immer noch für bestimmte Anwendungsbereiche eingeschränkt ist, im Gegensatz dazu, wo C++ verwendet werden kann.

Der Ansatz von c ++ bietet viel Leistung:
emcc --clear-cache --clear-ports
em++ -v -std=c++1y hello_world_sdl.cpp -s USE_SDL=2 -s USE_SDL_IMAGE=2 EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1 -s WASM=1 -o hello_world_sdl.html

Warum kann Golang kein ähnliches Verhalten haben?
UPDATE: Ich stehe korrigiert. Golang benötigt keine "-s"-Schalter aufgrund der cgo-Kompilieranweisungen, die in den go-Code eingebettet sind.

Das Löschen des Caches und das Löschen von Ports sind jedoch eine gute Idee, da bei der Migration zu verschiedenen golang-Build-Versionen, dh go1.9 zu go1.10, Fehler auftreten können. go1.10.3 bis go1.11 (wenn wir zu vgo lifestyle migrieren). Ich musste kürzlich ein "go build -a" zwischen go build-Versionen ausführen.
GOARCH=wasm GOOS=js go --clear-cache --clear-ports

Warum kann Golang kein ähnliches Verhalten haben?
GOARCH=wasm GOOS=js go --clear-cache --clear-ports

Der Cache von FWIW, Go erfordert keine explizite Löschung für die Korrektheit.

@neelance - Jetzt, da Rückrufe eingegangen sind, glaube ich, dass die grundlegende Unterstützung abgeschlossen ist. Sollen wir diesen Fehler schließen oder haben Sie etwas anderes im Sinn?

Ja, ich denke, wir können das jetzt schließen. 🎉

Gute Arbeit!!! @neelance

Das ist großartig, großartige Arbeit @neelance!

Änderung https://golang.org/cl/120057 erwähnt dieses Problem: doc/go1.11: mention GOOS/GOARCH values of WebAssembly port explicitly

Änderung https://golang.org/cl/120575 erwähnt dieses Problem: cmd/dist: skip non-std tests on js/wasm

Ist es angebracht, ein Thema zum Reduzieren der Dateigröße zu eröffnen (falls das überhaupt möglich ist)? Oder wird das woanders verfolgt?

@matthewp , Sie können gerne einen Webassembly-spezifischen Größenfehler öffnen, wenn Sie möchten. Die allgemeine ist #6853.

Änderung https://golang.org/cl/120958 erwähnt dieses Problem: net: re-implement built-in simulated network on JS and NaCl

Verfügt der Golang-Compiler über eine integrierte Kontrollflussintegrität (CFI)? Ich habe kürzlich Folgendes überflogen, das mit Schwachstellen in WASM zu tun hat, die mit CFI verhindert werden, das in den Clang-Compiler integriert ist:
https://www.fastly.com/blog/hijacking-control-flow-webassembly-program
https://github.com/trailofbits/clang-cfi-showcase/blob/master/cfi_vcall.cpp

Ich habe es nur überflogen, aber es scheint mir, als ob der Beitrag sagt: "WebAssembly ist keine Hochsprache wie JavaScript, sondern eine Niedrigsprache, daher können bestimmte Klassen von Fehlern auftreten, wenn die Quellsprache (C oder Go) dies zulässt ." Keine Überraschung. Das bedeutet, wenn Go solche Probleme hätte, würden sie auch für andere Architekturen gelten, nicht nur für WebAssembly.

Bei WebAssembly geht es hauptsächlich darum, den Browser vor schädlichem WebAssembly-Code zu schützen. Es geht nicht so sehr darum, Garantien innerhalb der WebAssembly-Instanz bereitzustellen (obwohl es einige davon gibt). Wie @neelance sagte, liegt es an den LanguageX-> WebAssembly-Compilern, alle erforderlichen Sicherheitsgarantien bereitzustellen.
Go hat kein CFI. Ich glaube nicht, dass es einfach wäre - an dem Punkt, an dem eine Methode beginnt, haben wir die vtable bereits verloren. Wir haben sogar die Tatsache verloren, dass eine vtable verwendet wurde.
Go ist anfällig für diesen Exploit, wenn Parallelität besteht. Zumindest im Moment hat der WebAssembly Go-Port (und WebAssembly, Punkt) keine Parallelität, daher ist dieser Exploit nur theoretisch. Die WebAssembly-Leute planen jedoch, irgendwann Parallelität zu implementieren.

@randall77 Wie wirkt sich das auf das einfache linux/amd64 aus? Ist das Risiko für WebAssembly irgendwie größer?

Das Risiko ist unabhängig von der Architektur gleich (mit der Ausnahme, dass WebAssembly noch keine Threads hat, also ist es für WebAssembly im Moment eigentlich null). Datenrennen können verwendet werden, um unsafe zu simulieren, ohne unsafe zu importieren.
Es wäre schwierig, eine solche Schwachstelle auszunutzen. Sie müssen entweder nicht vertrauenswürdigen Code einbinden oder irgendwie ein Gadget in einer vorhandenen Binärdatei finden und auslösen, das einen Datenwettlauf mit einem Schnittstellenwert durchführt, und dann eine Methode für das Ergebnis aufrufen.

Okay, wenn Ihr Go-Code also keine Datenrennen hat, sollte es in Ordnung sein. Wenn Sie nicht vertrauenswürdigen Code mit WebAssembly ausführen, können Sie außerdem sicherstellen, dass er der WebAssembly-Umgebung nicht entkommen kann, obwohl er Data Races haben kann, oder einfach unsafe verwenden. Danke für die interessanten Einblicke und entschuldigen Sie, dass dies für diese Ausgabe etwas vom Thema abweicht.

Je mehr ich diese Javascript-Nutzung innerhalb von Golang untersuche, desto mehr empfinde ich sie als eine Infektion, die die Qualität und die langfristige Wartung des Golang-Codes beeinträchtigen wird. Lassen Sie mich erklären. Hier ist ein Beispiel für eine wunderbare Wasm-Golang-App, die beeindruckende Augenweiden macht.

https://github.com/stdiopt/gowasm-experiments/blob/master/bouncy/main.go

Die Ergebnisse sind beeindruckend. Es war jedoch enttäuschend, weiter in den Code einzutauchen, der dies tatsächlich ermöglicht, da Sie jedes Mal, wenn Sie etwas von der Javascript-Seite aufrufen möchten, den Namen der Javascript-Funktion oder den Javascript-Wert als Zeichenfolge beschreiben müssen . Infolgedessen gibt es für den Golang-Compiler keine Möglichkeit, die JavaScript-Korrektheit zur Kompilierzeit zu überprüfen. Zur Laufzeit ist es "Fly by Prayer". Ich würde es vorziehen, Golang-Funktionen/Variablen/Typen überall für die langfristige Wartung zu sehen, da dies meiner bescheidenen Meinung nach den Zweck der Verwendung von Golang für Wasm zunichte macht. Übrigens verabscheue ich Javascript und habe es immer getan. Es ist zu freizügig. Warum hat sich eine solche Sprache in den Webbrowsern erhalten? Die Antwort entgeht mir.

Danke fürs Zuhören.

Ich stimme zu, dass das Aufrufen von JS mit Zeichenfolgen nicht die bessere Erfahrung ist. Vielleicht könnten wir Go-Schnittstellen aus den IDLs der Webplattformspezifikation generieren. Der Nachteil ist, wie man mit der Spezifikation Schritt halten kann, denn je nach Browser, auf dem es ausgeführt wird, sind die APIs nicht verfügbar, während auf der anderen Seite ständig neue Spezifikationen hinzukommen, wenn sich die Webplattform weiterentwickelt.

@omac777 Ich stimme dir zu. Deshalb hoffe ich, dass es rund um die JS-Low-Levels nette Go-Bibliotheken geben wird, so dass die meisten Benutzer syscall/js nie direkt berühren müssen. Ähnlich wie das syscall -Paket ist es hässlich und fast niemand verwendet es direkt. ;-)

@omac777 Für GopherJS verwenden viele Leute High-Level-Bindungen für verschiedene Browser-APIs und nicht direkt das Low-Level-Paket js . Ich vermute, dass ein ähnlicher Ansatz auch bei Wasm am beliebtesten sein wird. Ich gehe davon aus, dass viele der GopherJS-Bindungen Unterstützung für Wasm im selben Paket hinzufügen werden, und neue Pakete werden nach Bedarf erstellt.

Als Referenz siehe https://github.com/gopherjs/gopherjs/wiki/Bindings , https://dmitri.shuralyov.com/talks/2016/Go-in-the-browser/Go-in-the-browser. Folie #11 (und die folgenden 4 Folien) und https://github.com/dominikh/go-js-dom/issues/57.

Außerdem sollten wir bedenken, dass es eine Menge Dinge auf der Webassembly-Roadmap gibt:

https://webassembly.org/docs/future-features/

das wird die syscall Geschichte auf lange Sicht ziemlich verbessern

Verweisen Sie auf DOM und andere Web-API-Objekte direkt aus dem WebAssembly-Code;
Aufrufen von Web-APIs (übergeben von Primitiven oder DOM/GC/Web-API-Objekten) direkt von WebAssembly ohne Aufrufen über JavaScript; und
GC-Objekte effizient direkt aus dem WebAssembly-Code zuweisen und bearbeiten.

Wie auch immer, danke @neelance et. Al. für die Implementierung der ersten Version. So genial! 🥇

Was wäre, wenn es eine Go-Implementierung des DOM gäbe?

Dokumente und Skripte konnten unter Verwendung des Typsystems in Go geschrieben und ausgeführt werden.

Dann könnte Code aus dem Go-DOM generiert werden.

@fractalbach : Wenn die Hostbindung von WebAssembly von der Arbeitsgruppe bestätigt und implementiert wird, können Sie DOM-Manipulationen tatsächlich über WebAssembly durchführen. Dann wäre es sinnvoll, Bibliotheken auf hoher Ebene zu haben, um DOM, Dokumente und Skripte zu abstrahieren.

Aber vorher ist es nicht ganz so ansprechend zu tun.

Gehen Sie zu WebAssembly: Binden Sie Strukturen an JS-Referenzen

https://medium.com/@nlepage/go -webassembly-binding-structures-to-js-references-4eddd6fd4d23

Der Ansatz ist ansprechend. Die Verwendung ist ähnlich wie beim json-Marshalling/Unmarshalling innerhalb von Strukturen. Das macht es zu einer leicht übertragbaren Fähigkeit.

Das einzige, was fehlt, ist, wie man den gleichen Ansatz auf das Duck-Typing anwenden kann? Ich würde es vorziehen, die Funktionsdeklarationen nicht innerhalb der Struktur zu haben, sondern außerhalb davon eigenständig zu sein, genauso wie beim Duck-Typing. Wenn der Dienst vorhanden ist, kann er ihn verwenden. Auf diese Weise ist es leicht modifizierbar, ohne die Kernstruktur zu beeinträchtigen, die die verschiedenen gewünschten Nicht-Funktionswerte enthält. Duck-Typing-Felsen!

Nochmals vielen Dank @neelance für all deine Arbeit. Es wird sehr geschätzt.
Vielen Dank, Herr Nicolas Lepage, für Ihre Standpunkte. Sie helfen wirklich dabei, herauszufinden, was ein besserer Weg für die Interoperabilität mit all diesem Javascript-Rauschen für die Zwischenzeit sein könnte, bis die direkte Wasm-Schnittstelle abgeschlossen ist.

Hallo zusammen, dies ist ein stark frequentierter Thread mit vielen Abonnenten. Eine allgemeine Diskussion wie diese ist für diejenigen, die nur über das ursprüngliche Problem besorgt sind, nicht fruchtbar - nämlich WebAssembly-Unterstützung für Go zu haben.

Fühlen Sie sich frei, die Diskussion in geeigneten Foren fortzusetzen - golang-nuts/golang-dev. Oder wenn Sie etwas Bestimmtes im Sinn haben, öffnen Sie bitte ein neues Thema.

Danke.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen