Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Unified Diff: src/wasm/asm-wasm-builder.cc

Issue 1702293002: Add asm.js stdlib portion implementable as wasm opcodes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fixes Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/wasm/asm-wasm-builder.h ('k') | src/wasm/wasm-js.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/wasm/asm-wasm-builder.cc
diff --git a/src/wasm/asm-wasm-builder.cc b/src/wasm/asm-wasm-builder.cc
index ee5427b174d11e8736ca08af45e605e55f3ca8ab..abb69d5678565b5ebe91efa18f98c1dc1365e672 100644
--- a/src/wasm/asm-wasm-builder.cc
+++ b/src/wasm/asm-wasm-builder.cc
@@ -4,6 +4,12 @@
#include "src/v8.h"
+// Required to get M_E etc. in MSVC.
+#if defined(_WIN32)
+#define _USE_MATH_DEFINES
+#endif
+#include <math.h>
+
#include "src/wasm/asm-wasm-builder.h"
#include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-opcodes.h"
@@ -28,7 +34,7 @@ namespace wasm {
class AsmWasmBuilderImpl : public AstVisitor {
public:
AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal,
- Handle<Object> foreign)
+ Handle<Object> foreign, AsmTyper* typer)
: local_variables_(HashMap::PointersMatch,
ZoneHashMap::kDefaultHashMapCapacity,
ZoneAllocationPolicy(zone)),
@@ -46,6 +52,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
isolate_(isolate),
zone_(zone),
foreign_(foreign),
+ typer_(typer),
cache_(TypeCache::Get()),
breakable_blocks_(zone),
block_size_(0),
@@ -371,6 +378,58 @@ class AsmWasmBuilderImpl : public AstVisitor {
RECURSE(Visit(expr->else_expression()));
}
+ bool VisitStdlibConstant(Variable* var) {
+ AsmTyper::StandardMember standard_object =
+ typer_->VariableAsStandardMember(var);
+ double value;
+ switch (standard_object) {
+ case AsmTyper::kInfinity: {
+ value = std::numeric_limits<double>::infinity();
+ break;
+ }
+ case AsmTyper::kNaN: {
+ value = std::numeric_limits<double>::quiet_NaN();
+ break;
+ }
+ case AsmTyper::kMathE: {
+ value = M_E;
+ break;
+ }
+ case AsmTyper::kMathLN10: {
+ value = M_LN10;
+ break;
+ }
+ case AsmTyper::kMathLN2: {
+ value = M_LN2;
+ break;
+ }
+ case AsmTyper::kMathLOG10E: {
+ value = M_LOG10E;
+ break;
+ }
+ case AsmTyper::kMathLOG2E: {
+ value = M_LOG2E;
+ break;
+ }
+ case AsmTyper::kMathPI: {
+ value = M_PI;
+ break;
+ }
+ case AsmTyper::kMathSQRT1_2: {
+ value = M_SQRT1_2;
+ break;
+ }
+ case AsmTyper::kMathSQRT2: {
+ value = M_SQRT2;
+ break;
+ }
+ default: { return false; }
+ }
+ byte code[] = {WASM_F64(value)};
+ current_function_builder_->EmitCode(code, sizeof(code));
+ return true;
+ }
+
void VisitVariableProxy(VariableProxy* expr) {
if (in_function_) {
Variable* var = expr->var();
@@ -382,6 +441,9 @@ class AsmWasmBuilderImpl : public AstVisitor {
}
is_set_op_ = false;
} else {
+ if (VisitStdlibConstant(var)) {
+ return;
+ }
if (var->IsContextSlot()) {
current_function_builder_->Emit(kExprLoadGlobal);
} else {
@@ -589,29 +651,33 @@ class AsmWasmBuilderImpl : public AstVisitor {
UnLoadInitFunction();
return;
}
- // TODO(bradnelson): Get rid of this.
- if (TypeOf(expr->value()) == kAstStmt) {
- Property* prop = expr->value()->AsProperty();
- if (prop != nullptr) {
- VariableProxy* vp = prop->obj()->AsVariableProxy();
- if (vp != nullptr && vp->var()->IsParameter() &&
- vp->var()->index() == 1) {
- VariableProxy* target = expr->target()->AsVariableProxy();
- if (target->bounds().lower->Is(Type::Function())) {
- const AstRawString* name =
- prop->key()->AsLiteral()->AsRawPropertyName();
- imported_function_table_.AddImport(
- target->var(), name->raw_data(), name->length());
- }
- }
- }
- ArrayLiteral* funcs = expr->value()->AsArrayLiteral();
- if (funcs != nullptr &&
- funcs->bounds().lower->AsArray()->Element()->IsFunction()) {
+ Property* prop = expr->value()->AsProperty();
+ if (prop != nullptr) {
+ VariableProxy* vp = prop->obj()->AsVariableProxy();
+ if (vp != nullptr && vp->var()->IsParameter() &&
+ vp->var()->index() == 1) {
VariableProxy* target = expr->target()->AsVariableProxy();
- DCHECK_NOT_NULL(target);
- AddFunctionTable(target, funcs);
+ if (target->bounds().lower->Is(Type::Function())) {
+ const AstRawString* name =
+ prop->key()->AsLiteral()->AsRawPropertyName();
+ imported_function_table_.AddImport(target->var(), name->raw_data(),
+ name->length());
+ }
}
+ // Property values in module scope don't emit code, so return.
+ return;
+ }
+ ArrayLiteral* funcs = expr->value()->AsArrayLiteral();
+ if (funcs != nullptr &&
+ funcs->bounds().lower->AsArray()->Element()->IsFunction()) {
+ VariableProxy* target = expr->target()->AsVariableProxy();
+ DCHECK_NOT_NULL(target);
+ AddFunctionTable(target, funcs);
+ // Only add to the function table. No init needed.
+ return;
+ }
+ if (expr->value()->IsCallNew()) {
+ // No init code to emit for CallNew nodes.
return;
}
in_init = true;
@@ -765,11 +831,166 @@ class AsmWasmBuilderImpl : public AstVisitor {
UNREACHABLE();
}
+ bool VisitStdlibFunction(Call* call, VariableProxy* expr) {
+ Variable* var = expr->var();
+ AsmTyper::StandardMember standard_object =
+ typer_->VariableAsStandardMember(var);
+ ZoneList<Expression*>* args = call->arguments();
+ LocalType call_type = TypeOf(call);
+ switch (standard_object) {
+ case AsmTyper::kNone: {
+ return false;
+ }
+ case AsmTyper::kMathAcos: {
+ UNREACHABLE();
+ break; // TODO(bradnelson): Implement as external.
+ }
+ case AsmTyper::kMathAsin: {
+ UNREACHABLE();
+ break; // TODO(bradnelson): Implement as external.
+ }
+ case AsmTyper::kMathAtan: {
+ UNREACHABLE();
+ break; // TODO(bradnelson): Implement as external.
+ }
+ case AsmTyper::kMathCos: {
+ UNREACHABLE();
+ break; // TODO(bradnelson): Implement as external.
+ }
+ case AsmTyper::kMathSin: {
+ UNREACHABLE();
+ break; // TODO(bradnelson): Implement as external.
+ }
+ case AsmTyper::kMathTan: {
+ UNREACHABLE();
+ break; // TODO(bradnelson): Implement as external.
+ }
+ case AsmTyper::kMathExp: {
+ UNREACHABLE();
+ break; // TODO(bradnelson): Implement as external.
+ }
+ case AsmTyper::kMathLog: {
+ UNREACHABLE();
+ break; // TODO(bradnelson): Implement as external.
+ }
+ case AsmTyper::kMathCeil: {
+ if (call_type == kAstF32) {
+ current_function_builder_->Emit(kExprF32Ceil);
+ } else if (call_type == kAstF64) {
+ current_function_builder_->Emit(kExprF64Ceil);
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ }
+ case AsmTyper::kMathFloor: {
+ if (call_type == kAstF32) {
+ current_function_builder_->Emit(kExprF32Floor);
+ } else if (call_type == kAstF64) {
+ current_function_builder_->Emit(kExprF64Floor);
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ }
+ case AsmTyper::kMathSqrt: {
+ if (call_type == kAstF32) {
+ current_function_builder_->Emit(kExprF32Sqrt);
+ } else if (call_type == kAstF64) {
+ current_function_builder_->Emit(kExprF64Sqrt);
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ }
+ case AsmTyper::kMathAbs: {
+ // TODO(bradnelson): Handle signed.
+ if (call_type == kAstF32) {
+ current_function_builder_->Emit(kExprF32Abs);
+ } else if (call_type == kAstF64) {
+ current_function_builder_->Emit(kExprF64Abs);
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ }
+ case AsmTyper::kMathMin: {
+ // TODO(bradnelson): Handle signed.
+ // TODO(bradnelson): Change wasm to match Math.min in asm.js mode.
titzer 2016/02/23 15:57:58 Are we collecting tests for these somewhere?
bradn 2016/02/23 16:17:09 Will do.
+ if (call_type == kAstF32) {
+ current_function_builder_->Emit(kExprF32Min);
+ } else if (call_type == kAstF64) {
+ current_function_builder_->Emit(kExprF64Min);
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ }
+ case AsmTyper::kMathMax: {
+ // TODO(bradnelson): Handle signed.
+ // TODO(bradnelson): Change wasm to match Math.max in asm.js mode.
+ if (call_type == kAstF32) {
+ current_function_builder_->Emit(kExprF32Max);
+ } else if (call_type == kAstF64) {
+ current_function_builder_->Emit(kExprF64Max);
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ }
+ case AsmTyper::kMathAtan2: {
+ UNREACHABLE();
+ break; // TODO(bradnelson): Implement as external.
+ }
+ case AsmTyper::kMathPow: {
+ UNREACHABLE();
+ break; // TODO(bradnelson): Implement as external.
+ }
+ case AsmTyper::kMathImul: {
+ current_function_builder_->Emit(kExprI32Mul);
+ break;
+ }
+ case AsmTyper::kMathFround: {
+ DCHECK(args->length() == 1);
+ Literal* literal = args->at(0)->AsLiteral();
+ if (literal != nullptr) {
+ if (literal->raw_value()->IsNumber()) {
+ float val = static_cast<float>(literal->raw_value()->AsNumber());
+ byte code[] = {WASM_F32(val)};
+ current_function_builder_->EmitCode(code, sizeof(code));
+ return true;
+ }
+ }
+ break;
+ }
+ default: {
+ UNREACHABLE();
+ break;
+ }
+ }
+ VisitCallArgs(call);
+ return true;
+ }
+
+ void VisitCallArgs(Call* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ for (int i = 0; i < args->length(); ++i) {
+ Expression* arg = args->at(i);
+ RECURSE(Visit(arg));
+ }
+ }
+
void VisitCall(Call* expr) {
Call::CallType call_type = expr->GetCallType(isolate_);
switch (call_type) {
case Call::OTHER_CALL: {
DCHECK(in_function_);
+ VariableProxy* proxy = expr->expression()->AsVariableProxy();
+ if (proxy != nullptr) {
+ if (VisitStdlibFunction(expr, proxy)) {
+ return;
+ }
+ }
uint16_t index;
VariableProxy* vp = expr->expression()->AsVariableProxy();
if (vp != nullptr &&
@@ -813,11 +1034,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
default:
UNREACHABLE();
}
- ZoneList<Expression*>* args = expr->arguments();
- for (int i = 0; i < args->length(); ++i) {
- Expression* arg = args->at(i);
- RECURSE(Visit(arg));
- }
+ VisitCallArgs(expr);
}
void VisitCallNew(CallNew* expr) { UNREACHABLE(); }
@@ -1262,6 +1479,7 @@ class AsmWasmBuilderImpl : public AstVisitor {
Isolate* isolate_;
Zone* zone_;
Handle<Object> foreign_;
+ AsmTyper* typer_;
TypeCache const& cache_;
ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_;
int block_size_;
@@ -1277,13 +1495,18 @@ class AsmWasmBuilderImpl : public AstVisitor {
};
AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone,
- FunctionLiteral* literal, Handle<Object> foreign)
- : isolate_(isolate), zone_(zone), literal_(literal), foreign_(foreign) {}
+ FunctionLiteral* literal, Handle<Object> foreign,
+ AsmTyper* typer)
+ : isolate_(isolate),
+ zone_(zone),
+ literal_(literal),
+ foreign_(foreign),
+ typer_(typer) {}
// TODO(aseemgarg): probably should take zone (to write wasm to) as input so
// that zone in constructor may be thrown away once wasm module is written.
WasmModuleIndex* AsmWasmBuilder::Run() {
- AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_);
+ AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_);
impl.Compile();
WasmModuleWriter* writer = impl.builder_->Build(zone_);
return writer->WriteTo(zone_);
« no previous file with comments | « src/wasm/asm-wasm-builder.h ('k') | src/wasm/wasm-js.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698