Chromium Code Reviews| Index: src/wasm/asm-wasm-builder.cc |
| diff --git a/src/wasm/asm-wasm-builder.cc b/src/wasm/asm-wasm-builder.cc |
| index 00f459316f6a4d69581f1ca6039ccb9b3222b386..b70aa34999136ef1bf61718349446e0dbdc6b02b 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,67 @@ class AsmWasmBuilderImpl : public AstVisitor { |
| RECURSE(Visit(expr->else_expression())); |
| } |
| + bool VisitStdlibConstant(Variable* var) { |
| + AsmTyper::StandardMember standard_object = |
| + typer_->VariableAsStandardMember(var); |
| + switch (standard_object) { |
| + case AsmTyper::kInfinity: { |
| + double infinity = std::numeric_limits<double>::infinity(); |
| + byte code[] = {WASM_F64(infinity)}; |
| + current_function_builder_->EmitCode(code, sizeof(code)); |
|
aseemgarg
2016/02/22 22:15:53
move the EmitCode and return to outside of cases a
bradnelson
2016/02/23 09:48:54
Done.
|
| + return true; |
| + } |
| + case AsmTyper::kNaN: { |
| + double nan = std::numeric_limits<double>::signaling_NaN(); |
| + byte code[] = {WASM_F64(nan)}; |
| + current_function_builder_->EmitCode(code, sizeof(code)); |
| + return true; |
| + } |
| + case AsmTyper::kMathE: { |
| + byte code[] = {WASM_F64(M_E)}; |
| + current_function_builder_->EmitCode(code, sizeof(code)); |
| + return true; |
| + } |
| + case AsmTyper::kMathLN10: { |
| + byte code[] = {WASM_F64(M_LN10)}; |
| + current_function_builder_->EmitCode(code, sizeof(code)); |
| + return true; |
| + } |
| + case AsmTyper::kMathLN2: { |
| + byte code[] = {WASM_F64(M_LN2)}; |
| + current_function_builder_->EmitCode(code, sizeof(code)); |
| + return true; |
| + } |
| + case AsmTyper::kMathLOG10E: { |
| + byte code[] = {WASM_F64(M_LOG10E)}; |
| + current_function_builder_->EmitCode(code, sizeof(code)); |
| + return true; |
| + } |
| + case AsmTyper::kMathLOG2E: { |
| + byte code[] = {WASM_F64(M_LOG2E)}; |
| + current_function_builder_->EmitCode(code, sizeof(code)); |
| + return true; |
| + } |
| + case AsmTyper::kMathPI: { |
| + byte code[] = {WASM_F64(M_PI)}; |
| + current_function_builder_->EmitCode(code, sizeof(code)); |
| + return true; |
| + } |
| + case AsmTyper::kMathSQRT1_2: { |
| + byte code[] = {WASM_F64(M_SQRT1_2)}; |
| + current_function_builder_->EmitCode(code, sizeof(code)); |
| + return true; |
| + } |
| + case AsmTyper::kMathSQRT2: { |
| + byte code[] = {WASM_F64(M_SQRT2)}; |
| + current_function_builder_->EmitCode(code, sizeof(code)); |
| + return true; |
| + } |
| + default: { break; } |
| + } |
| + return false; |
| + } |
| + |
| void VisitVariableProxy(VariableProxy* expr) { |
| if (in_function_) { |
| Variable* var = expr->var(); |
| @@ -382,6 +450,9 @@ class AsmWasmBuilderImpl : public AstVisitor { |
| } |
| is_set_op_ = false; |
| } else { |
| + if (VisitStdlibConstant(var)) { |
| + return; |
| + } |
| if (var->IsContextSlot()) { |
| current_function_builder_->Emit(kExprLoadGlobal); |
| } else { |
| @@ -589,6 +660,13 @@ class AsmWasmBuilderImpl : public AstVisitor { |
| UnLoadInitFunction(); |
| return; |
| } |
| + Property* prop = expr->value()->AsProperty(); |
|
aseemgarg
2016/02/22 22:15:53
This doesn't seem quite right. Stdlib constants wo
bradnelson
2016/02/23 09:48:54
So unlike foreign globals, stdlib functions come i
|
| + if (prop != nullptr) { |
| + if (TypeOf(expr->value()) != kAstStmt) { |
| + // Assume it's part of stdlib. |
| + return; |
| + } |
| + } |
| // TODO(bradnelson): Get rid of this. |
| if (TypeOf(expr->value()) == kAstStmt) { |
| Property* prop = expr->value()->AsProperty(); |
| @@ -765,11 +843,159 @@ 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. |
| + 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 != NULL) { |
| + 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: { break; } |
| + } |
| + // Visit arguments. |
|
aseemgarg
2016/02/22 22:15:53
The visiting of args should be done in the visit c
bradnelson
2016/02/23 09:48:55
So sharing the later call is tricky, as Fround wan
|
| + for (int i = 0; i < args->length(); ++i) { |
| + Expression* arg = args->at(i); |
| + Visit(arg); |
| + } |
| + return true; |
| + } |
| + |
| 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 != NULL) { |
| + if (VisitStdlibFunction(expr, proxy)) { |
| + return; |
| + } |
| + } |
| uint16_t index; |
| VariableProxy* vp = expr->expression()->AsVariableProxy(); |
| if (vp != nullptr && |
| @@ -1266,6 +1492,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_; |
| @@ -1281,13 +1508,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_); |