# Asm.js

asm.js é um subconjunto de JavaScript projetado para permitir que software de computador escrito em linguagens como C sejam executados como aplicativos da web, enquanto mantém características de desempenho consideravelmente melhores do que o JavaScript padrão, que é a linguagem típica usada para tais aplicativos.
o asm.js consiste em um subconjunto estrito de JavaScript, para o qual o código escrito em linguagens estaticamente tipadas com gerenciamento de memória manual (como C) é traduzido por um compilador de fonte para fonte como o Emscripten (baseado em LLVM). O desempenho é melhorado ao limitar os recursos da linguagem àqueles que podem ser otimizados com antecedência e outras melhorias de desempenho.
O Mozilla Firefox foi o primeiro navegador da web a implementar otimizações específicas para o asm.js, a partir da versão 22.
O asm.js foi substituído por WebAssembly. Consulte § Deprecação abaixo.

## Design

O asm.js permite melhorias significativas de desempenho para aplicativos da web, mas não tem como objetivo melhorar o desempenho do código JavaScript escrito à mão, nem permite nada além do desempenho aprimorado.
Destina-se a ter características de desempenho mais próximas das do código nativo do que o JavaScript padrão, limitando os recursos da linguagem àqueles passíveis de otimização antecipada e outras melhorias de desempenho. Ao usar um subconjunto de JavaScript, o asm.js é amplamente compatível com todos os principais navegadores da web, ao contrário de abordagens alternativas como o Google Native Client.

## Geração de código

O asm.js normalmente não é escrito diretamente: em vez disso, como uma linguagem intermediária, ele é gerado por meio do uso de um compilador que pega o código-fonte em uma linguagem como C++ e gera asm.js.
Por exemplo, dado o seguinte código em C:
Emscripten produziria o seguinte código em JS:
Observe a adição de |0 e a falta de especificadores de tipo. Em JavaScript, os operadores bit a bit convertem seus operandos em inteiros assinados de 32 bits e fornecem resultados inteiros. Isso significa que um OR bit a bit com zero converte um valor em um inteiro (uma apresentação "conceitual" muito simples de operadores bit a bit pode não lidar com a conversão de tipo, mas toda linguagem de programação define operadores para sua própria conveniência, como o Javascript faz aqui) . Ao fazer isso para cada parâmetro, isso garante que, se a função for chamada de um código externo, o valor será convertido para o tipo correto. Isso também é usado no valor de retorno, neste caso, para garantir que o resultado da adição de 1 a i seja um número inteiro (caso contrário, ele poderia se tornar muito grande) e para marcar o tipo de retorno da função. Essas conversões são exigidas pelo asm.js, para que um compilador otimizador possa produzir código nativo ahead-of-time altamente eficiente. Nesse compilador otimizador, nenhuma conversão é executada quando o código asm.js chama outro código asm.js, pois os especificadores de tipo necessários significam que é garantido que os valores já terão o tipo correto. Além disso, em vez de realizar uma adição de ponto flutuante e converter para um número inteiro, ele pode simplesmente fazer uma operação de número inteiro nativo. Juntos, isso leva a benefícios em desempenho significativos.
Aqui está outro exemplo para calcular o comprimento de uma string:
Isso resultaria no seguinte código em asm.js:
No código gerado, a variável MEM8 é na verdade uma "visualização" byte a byte de um buffer tipado, que serve como o "heap" do código em asm.js.

## Desempenho

Como o asm.js é executado em um navegador, o desempenho depende muito do navegador e do hardware. Os benchmarks preliminares de programas C compilados para asm.js estão geralmente em um fator de lentidão de 2 em relação à compilação nativa com Clang.
Muito desse ganho de desempenho em relação ao JavaScript normal é devido a 100% de consistência de tipo e virtualmente nenhuma coleta de lixo (a memória é gerenciada manualmente em uma grande matriz tipada). Este modelo mais simples, sem comportamento dinâmico, sem alocação ou desalocação de memória, apenas um conjunto estreito de inteiros bem definidos e operações de ponto flutuante permite um desempenho muito maior e potencial de otimização.
O benchmark da Mozilla de dezembro de 2013 mostrou melhorias significativas: "Firefox com otimizações float32 pode rodar todos esses benchmarks em cerca de 1,5× mais lento do que o nativo, ou melhor." A Mozilla aponta que o desempenho do código compilado nativamente não é uma medida única, mas sim um intervalo, com diferentes compiladores nativos (neste caso Clang e GCC) entregando código de desempenho diferente. "Na verdade, em alguns benchmarks, como Box2D, FASTA e cópia, asm.js é tão próximo ou mais próximo do Clang do que o Clang está do GCC. Em um caso, o asm.js até supera o Clang por pouco no Box2D."

## Implementações

O projeto Emscripten fornece ferramentas que podem ser usadas para compilar bases de código C e C ++ (ou qualquer outra linguagem que possa ser convertida para LLVM IR) em asm.js.
Todos os navegadores com suporte para ECMAScript 6 devem ser capazes de executar o código asm.js, pois é um subconjunto dessa especificação. No entanto, como os recursos foram adicionados nessa edição para habilitar o suporte completo para asm.js (Math.fround), navegadores mais antigos sem esses recursos podem encontrar problemas.
Algumas implementações de navegador são especialmente otimizadas para asm.js:
* Mozilla Firefox foi o primeiro navegador da web a implementar otimizações específicas do asm.js, começando com o Firefox 22. OdinMonkey, o compilador asm.js da Mozilla usado no Firefox, é um componente do IonMonkey, o compilador JIT do SpiderMonkey.
* A Microsoft está implementando suporte para asm.js em Chakra, o mecanismo JavaScript usado pelo Microsoft Edge, realizando validação para produzir código JIT altamente otimizado.
* As otimizações do motor JavaScript V8 do Google Chrome no Chrome 28 fizeram benchmarks do asm.js mais de duas vezes mais rápido do que as versões anteriores do Chrome, embora o V8 do Chrome não use compilação antecipada.

## Adoção

Quase todos os aplicativos atuais baseados em asm.js são aplicativos C/C++ compilados em asm.js usando Emscripten ou Mandreel. Com isso em mente, o tipo de aplicativo que terá como alvo o asm.js em um futuro próximo são aqueles que se beneficiarão da portabilidade de execução em um navegador, mas que têm um nível de complexidade para o qual um porte direto para JavaScript seria inviável.
Até agora, uma série de linguagens de programação, frameworks de aplicativos, programas, bibliotecas, jogos, motores de jogos e outros softwares já foram portados. Alguns deles são listados abaixo.

### Linguagens de programação

* C/C++: Clang e LLVM
* Rust: tem como alvo o Emscripten
* Lua VM: Máquina virtual Lua
* Perl: porte de (micro)perl-5.16.3
* Python – porte de CPython
* Ruby – porte de Ruby

### Frameworks de aplicativos

* pepper.js: Portes de diversos apps PNaCl (earth, voronoi, bullet, etc.)
* Qt: portes de vários demos da Qt, mais os aplicativos do KDE, como o Kate

### Programas e bibliotecas

* OpenGL, SDL, e SDL2
* Vim (Vi IMproved)
* FreeType: renderização de fontes TrueType em JavaScript, usando FreeType
* SQLite
* GNU Privacy Guard
* ctags
* gnuplot
* Graphviz
* zlib

### Motores de jogo

* Unreal Engine 3: foi portado em 4 dias
* Unreal Engine 4
* Unity
* ScummVM, que suporta vários jogos clássicos de aventura
* Godot

### Jogos

* Doom: os ativos do jogo em código aberto Freedoom em execução no PrBoom, que é baseado no código em código aberto Doom
* SuperTux
* Dune II via OpenDune
* BananaBread baseado em Cube 2
* Todos os jogos do Humble Mozilla Bundle (Super Hexagon, AaAaAA! for the Awesome, Osmos, Zen Bound 2, Dustforce DX, Voxatron, FTL: Advanced Edition and Democracy 3)

### Emuladores

* EM-DOSBox: um porte do DOSBox para o Emscripten
* Start9.io: uma plataforma de emulação da web visando múltiplas arquiteturas de jogos
* JSMESS: um porte do emulador MESS para muitos consoles de jogos e sistemas de computadores

### Matemática

* HTML5 Fractal Playground – desenha fractais gerados por função iterativa, como o conjunto de Mandelbrot.

## Deprecação

O asm.js se tornou obsoleto principalmente com a introdução do WebAssembly (wasm), que tem um formato de bytecode que é mais rápido de analisar. Os esforços para estender o JavaScript com mais recursos de baixo nível, como SIMD.js, também foram suspensos desde 2017.
o asm.js permanece útil principalmente como um "substituto" para o wasm, por meio de um programa escrito pela organização WebAssembly que converte o wasm em asm.js. Não há um conversor dedicado de asm.js para wasm, mas os compiladores TypeScript-para-wasm podem ser usados parcialmente. O emissor WebAssembly de referência binaryen costumava conter um módulo asm2wasm, mas foi removido depois que o Emscripten parou de usá-lo.