| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 // Required to get M_E etc. in MSVC. | 7 // Required to get M_E etc. in MSVC. |
| 8 #if defined(_WIN32) | 8 #if defined(_WIN32) |
| 9 #define _USE_MATH_DEFINES | 9 #define _USE_MATH_DEFINES |
| 10 #endif | 10 #endif |
| 11 #include <math.h> | 11 #include <math.h> |
| 12 | 12 |
| 13 #include "src/asmjs/asm-types.h" |
| 13 #include "src/asmjs/asm-wasm-builder.h" | 14 #include "src/asmjs/asm-wasm-builder.h" |
| 14 #include "src/wasm/switch-logic.h" | 15 #include "src/wasm/switch-logic.h" |
| 15 #include "src/wasm/wasm-macro-gen.h" | 16 #include "src/wasm/wasm-macro-gen.h" |
| 16 #include "src/wasm/wasm-opcodes.h" | 17 #include "src/wasm/wasm-opcodes.h" |
| 17 | 18 |
| 18 #include "src/ast/ast.h" | 19 #include "src/ast/ast.h" |
| 19 #include "src/ast/scopes.h" | 20 #include "src/ast/scopes.h" |
| 20 #include "src/codegen.h" | 21 #include "src/codegen.h" |
| 21 #include "src/type-cache.h" | |
| 22 | 22 |
| 23 namespace v8 { | 23 namespace v8 { |
| 24 namespace internal { | 24 namespace internal { |
| 25 namespace wasm { | 25 namespace wasm { |
| 26 | 26 |
| 27 #define RECURSE(call) \ | 27 #define RECURSE(call) \ |
| 28 do { \ | 28 do { \ |
| 29 DCHECK(!HasStackOverflow()); \ | 29 DCHECK(!HasStackOverflow()); \ |
| 30 call; \ | 30 call; \ |
| 31 if (HasStackOverflow()) return; \ | 31 if (HasStackOverflow()) return; \ |
| (...skipping 20 matching lines...) Expand all Loading... |
| 52 global_variables_(base::HashMap::PointersMatch, | 52 global_variables_(base::HashMap::PointersMatch, |
| 53 ZoneHashMap::kDefaultHashMapCapacity, | 53 ZoneHashMap::kDefaultHashMapCapacity, |
| 54 ZoneAllocationPolicy(zone)), | 54 ZoneAllocationPolicy(zone)), |
| 55 scope_(kModuleScope), | 55 scope_(kModuleScope), |
| 56 builder_(new (zone) WasmModuleBuilder(zone)), | 56 builder_(new (zone) WasmModuleBuilder(zone)), |
| 57 current_function_builder_(nullptr), | 57 current_function_builder_(nullptr), |
| 58 literal_(literal), | 58 literal_(literal), |
| 59 isolate_(isolate), | 59 isolate_(isolate), |
| 60 zone_(zone), | 60 zone_(zone), |
| 61 typer_(typer), | 61 typer_(typer), |
| 62 cache_(TypeCache::Get()), | |
| 63 breakable_blocks_(zone), | 62 breakable_blocks_(zone), |
| 64 foreign_variables_(zone), | 63 foreign_variables_(zone), |
| 65 init_function_index_(0), | 64 init_function_index_(0), |
| 66 foreign_init_function_index_(0), | 65 foreign_init_function_index_(0), |
| 67 next_table_index_(0), | 66 next_table_index_(0), |
| 68 function_tables_(base::HashMap::PointersMatch, | 67 function_tables_(base::HashMap::PointersMatch, |
| 69 ZoneHashMap::kDefaultHashMapCapacity, | 68 ZoneHashMap::kDefaultHashMapCapacity, |
| 70 ZoneAllocationPolicy(zone)), | 69 ZoneAllocationPolicy(zone)), |
| 71 imported_function_table_(this), | 70 imported_function_table_(this) { |
| 72 bounds_(typer->bounds()) { | |
| 73 InitializeAstVisitor(isolate); | 71 InitializeAstVisitor(isolate); |
| 74 } | 72 } |
| 75 | 73 |
| 76 void InitializeInitFunction() { | 74 void InitializeInitFunction() { |
| 77 init_function_index_ = builder_->AddFunction(); | 75 init_function_index_ = builder_->AddFunction(); |
| 78 FunctionSig::Builder b(zone(), 0, 0); | 76 FunctionSig::Builder b(zone(), 0, 0); |
| 79 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 77 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
| 80 current_function_builder_->SetSignature(b.Build()); | 78 current_function_builder_->SetSignature(b.Build()); |
| 81 builder_->MarkStartFunction(init_function_index_); | 79 builder_->MarkStartFunction(init_function_index_); |
| 82 current_function_builder_ = nullptr; | 80 current_function_builder_ = nullptr; |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 ZoneVector<BlockVisitor*> blocks(zone_); | 350 ZoneVector<BlockVisitor*> blocks(zone_); |
| 353 ZoneVector<int32_t> cases(zone_); | 351 ZoneVector<int32_t> cases(zone_); |
| 354 ZoneMap<int, unsigned int> case_to_block(zone_); | 352 ZoneMap<int, unsigned int> case_to_block(zone_); |
| 355 bool has_default = false; | 353 bool has_default = false; |
| 356 for (int i = case_count - 1; i >= 0; i--) { | 354 for (int i = case_count - 1; i >= 0; i--) { |
| 357 CaseClause* clause = clauses->at(i); | 355 CaseClause* clause = clauses->at(i); |
| 358 blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false)); | 356 blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false)); |
| 359 if (!clause->is_default()) { | 357 if (!clause->is_default()) { |
| 360 Literal* label = clause->label()->AsLiteral(); | 358 Literal* label = clause->label()->AsLiteral(); |
| 361 Handle<Object> value = label->value(); | 359 Handle<Object> value = label->value(); |
| 362 DCHECK(value->IsNumber() && | |
| 363 bounds_->get(label).upper->Is(cache_.kAsmSigned)); | |
| 364 int32_t label_value; | 360 int32_t label_value; |
| 365 if (!value->ToInt32(&label_value)) { | 361 bool label_is_i32 = value->ToInt32(&label_value); |
| 366 UNREACHABLE(); | 362 DCHECK(value->IsNumber() && label_is_i32); |
| 367 } | 363 (void)label_is_i32; |
| 368 case_to_block[label_value] = i; | 364 case_to_block[label_value] = i; |
| 369 cases.push_back(label_value); | 365 cases.push_back(label_value); |
| 370 } else { | 366 } else { |
| 371 DCHECK_EQ(i, case_count - 1); | 367 DCHECK_EQ(i, case_count - 1); |
| 372 has_default = true; | 368 has_default = true; |
| 373 } | 369 } |
| 374 } | 370 } |
| 375 if (!has_default || case_count > 1) { | 371 if (!has_default || case_count > 1) { |
| 376 int default_block = has_default ? case_count - 1 : case_count; | 372 int default_block = has_default ? case_count - 1 : case_count; |
| 377 BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false); | 373 BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 UNREACHABLE(); | 448 UNREACHABLE(); |
| 453 } | 449 } |
| 454 | 450 |
| 455 void VisitDebuggerStatement(DebuggerStatement* stmt) override { | 451 void VisitDebuggerStatement(DebuggerStatement* stmt) override { |
| 456 UNREACHABLE(); | 452 UNREACHABLE(); |
| 457 } | 453 } |
| 458 | 454 |
| 459 void VisitFunctionLiteral(FunctionLiteral* expr) override { | 455 void VisitFunctionLiteral(FunctionLiteral* expr) override { |
| 460 Scope* scope = expr->scope(); | 456 Scope* scope = expr->scope(); |
| 461 if (scope_ == kFuncScope) { | 457 if (scope_ == kFuncScope) { |
| 462 if (bounds_->get(expr).lower->IsFunction()) { | 458 if (auto* func_type = typer_->TypeOf(expr)->AsFunctionType()) { |
| 463 // Build the signature for the function. | 459 // Build the signature for the function. |
| 464 FunctionType* func_type = bounds_->get(expr).lower->AsFunction(); | 460 LocalType return_type = TypeFrom(func_type->ReturnType()); |
| 465 LocalType return_type = TypeFrom(func_type->Result()); | 461 const auto& arguments = func_type->Arguments(); |
| 466 FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1, | 462 FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1, |
| 467 func_type->Arity()); | 463 arguments.size()); |
| 468 if (return_type != kAstStmt) b.AddReturn(return_type); | 464 if (return_type != kAstStmt) b.AddReturn(return_type); |
| 469 for (int i = 0; i < expr->parameter_count(); ++i) { | 465 for (int i = 0; i < expr->parameter_count(); ++i) { |
| 470 LocalType type = TypeFrom(func_type->Parameter(i)); | 466 LocalType type = TypeFrom(arguments[i]); |
| 471 DCHECK_NE(kAstStmt, type); | 467 DCHECK_NE(kAstStmt, type); |
| 472 b.AddParam(type); | 468 b.AddParam(type); |
| 473 InsertParameter(scope->parameter(i), type, i); | 469 InsertParameter(scope->parameter(i), type, i); |
| 474 } | 470 } |
| 475 current_function_builder_->SetSignature(b.Build()); | 471 current_function_builder_->SetSignature(b.Build()); |
| 476 } else { | 472 } else { |
| 477 UNREACHABLE(); | 473 UNREACHABLE(); |
| 478 } | 474 } |
| 479 } | 475 } |
| 480 RECURSE(VisitStatements(expr->body())); | 476 RECURSE(VisitStatements(expr->body())); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 LookupOrInsertLocal(var, var_type)); | 562 LookupOrInsertLocal(var, var_type)); |
| 567 } | 563 } |
| 568 } | 564 } |
| 569 } | 565 } |
| 570 | 566 |
| 571 void VisitLiteral(Literal* expr) override { | 567 void VisitLiteral(Literal* expr) override { |
| 572 Handle<Object> value = expr->value(); | 568 Handle<Object> value = expr->value(); |
| 573 if (!value->IsNumber() || (scope_ != kFuncScope && scope_ != kInitScope)) { | 569 if (!value->IsNumber() || (scope_ != kFuncScope && scope_ != kInitScope)) { |
| 574 return; | 570 return; |
| 575 } | 571 } |
| 576 Type* type = bounds_->get(expr).upper; | 572 AsmType* type = typer_->TypeOf(expr); |
| 577 if (type->Is(cache_.kAsmSigned)) { | 573 DCHECK_NE(type, AsmType::None()); |
| 574 |
| 575 if (type->IsA(AsmType::Signed())) { |
| 578 int32_t i = 0; | 576 int32_t i = 0; |
| 579 if (!value->ToInt32(&i)) { | 577 if (!value->ToInt32(&i)) { |
| 580 UNREACHABLE(); | 578 UNREACHABLE(); |
| 581 } | 579 } |
| 582 byte code[] = {WASM_I32V(i)}; | 580 byte code[] = {WASM_I32V(i)}; |
| 583 current_function_builder_->EmitCode(code, sizeof(code)); | 581 current_function_builder_->EmitCode(code, sizeof(code)); |
| 584 } else if (type->Is(cache_.kAsmUnsigned) || type->Is(cache_.kAsmFixnum)) { | 582 } else if (type->IsA(AsmType::Unsigned()) || type->IsA(AsmType::FixNum())) { |
| 585 uint32_t u = 0; | 583 uint32_t u = 0; |
| 586 if (!value->ToUint32(&u)) { | 584 if (!value->ToUint32(&u)) { |
| 587 UNREACHABLE(); | 585 UNREACHABLE(); |
| 588 } | 586 } |
| 589 int32_t i = static_cast<int32_t>(u); | 587 int32_t i = static_cast<int32_t>(u); |
| 590 byte code[] = {WASM_I32V(i)}; | 588 byte code[] = {WASM_I32V(i)}; |
| 591 current_function_builder_->EmitCode(code, sizeof(code)); | 589 current_function_builder_->EmitCode(code, sizeof(code)); |
| 592 } else if (type->Is(cache_.kAsmDouble)) { | 590 } else if (type->IsA(AsmType::Double())) { |
| 593 double val = expr->raw_value()->AsNumber(); | 591 double val = expr->raw_value()->AsNumber(); |
| 594 byte code[] = {WASM_F64(val)}; | 592 byte code[] = {WASM_F64(val)}; |
| 595 current_function_builder_->EmitCode(code, sizeof(code)); | 593 current_function_builder_->EmitCode(code, sizeof(code)); |
| 596 } else { | 594 } else { |
| 597 UNREACHABLE(); | 595 UNREACHABLE(); |
| 598 } | 596 } |
| 599 } | 597 } |
| 600 | 598 |
| 601 void VisitRegExpLiteral(RegExpLiteral* expr) override { UNREACHABLE(); } | 599 void VisitRegExpLiteral(RegExpLiteral* expr) override { UNREACHABLE(); } |
| 602 | 600 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 628 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 626 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
| 629 scope_ = kInitScope; | 627 scope_ = kInitScope; |
| 630 } | 628 } |
| 631 | 629 |
| 632 void UnLoadInitFunction() { | 630 void UnLoadInitFunction() { |
| 633 scope_ = kModuleScope; | 631 scope_ = kModuleScope; |
| 634 current_function_builder_ = nullptr; | 632 current_function_builder_ = nullptr; |
| 635 } | 633 } |
| 636 | 634 |
| 637 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { | 635 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { |
| 638 FunctionType* func_type = | 636 auto* func_tbl_type = typer_->TypeOf(funcs)->AsFunctionTableType(); |
| 639 bounds_->get(funcs).lower->AsArray()->Element()->AsFunction(); | 637 DCHECK_NOT_NULL(func_tbl_type); |
| 640 LocalType return_type = TypeFrom(func_type->Result()); | 638 auto* func_type = func_tbl_type->signature()->AsFunctionType(); |
| 639 const auto& arguments = func_type->Arguments(); |
| 640 LocalType return_type = TypeFrom(func_type->ReturnType()); |
| 641 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 641 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 642 func_type->Arity()); | 642 arguments.size()); |
| 643 if (return_type != kAstStmt) { | 643 if (return_type != kAstStmt) { |
| 644 sig.AddReturn(static_cast<LocalType>(return_type)); | 644 sig.AddReturn(return_type); |
| 645 } | 645 } |
| 646 for (int i = 0; i < func_type->Arity(); ++i) { | 646 for (auto* arg : arguments) { |
| 647 sig.AddParam(TypeFrom(func_type->Parameter(i))); | 647 sig.AddParam(TypeFrom(arg)); |
| 648 } | 648 } |
| 649 uint32_t signature_index = builder_->AddSignature(sig.Build()); | 649 uint32_t signature_index = builder_->AddSignature(sig.Build()); |
| 650 InsertFunctionTable(table->var(), next_table_index_, signature_index); | 650 InsertFunctionTable(table->var(), next_table_index_, signature_index); |
| 651 next_table_index_ += funcs->values()->length(); | 651 next_table_index_ += funcs->values()->length(); |
| 652 for (int i = 0; i < funcs->values()->length(); ++i) { | 652 for (int i = 0; i < funcs->values()->length(); ++i) { |
| 653 VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); | 653 VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); |
| 654 DCHECK_NOT_NULL(func); | 654 DCHECK_NOT_NULL(func); |
| 655 builder_->AddIndirectFunction(LookupOrInsertFunction(func->var())); | 655 builder_->AddIndirectFunction(LookupOrInsertFunction(func->var())); |
| 656 } | 656 } |
| 657 } | 657 } |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 } else { | 798 } else { |
| 799 current_function_builder_->EmitSetLocal( | 799 current_function_builder_->EmitSetLocal( |
| 800 LookupOrInsertLocal(var, var_type)); | 800 LookupOrInsertLocal(var, var_type)); |
| 801 } | 801 } |
| 802 } | 802 } |
| 803 | 803 |
| 804 Property* target_prop = expr->target()->AsProperty(); | 804 Property* target_prop = expr->target()->AsProperty(); |
| 805 if (target_prop != nullptr) { | 805 if (target_prop != nullptr) { |
| 806 // Left hand side is a property access, i.e. the asm.js heap. | 806 // Left hand side is a property access, i.e. the asm.js heap. |
| 807 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && | 807 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && |
| 808 bounds_->get(expr->target()->AsProperty()->obj()) | 808 typer_->TypeOf(expr->target()->AsProperty()->obj()) |
| 809 .lower->Is(cache_.kFloat32Array)) { | 809 ->IsA(AsmType::Float32Array())) { |
| 810 current_function_builder_->Emit(kExprF32ConvertF64); | 810 current_function_builder_->Emit(kExprF32ConvertF64); |
| 811 } | 811 } |
| 812 WasmOpcode opcode; | 812 WasmOpcode opcode; |
| 813 if (type == MachineType::Int8()) { | 813 if (type == MachineType::Int8()) { |
| 814 opcode = kExprI32AsmjsStoreMem8; | 814 opcode = kExprI32AsmjsStoreMem8; |
| 815 } else if (type == MachineType::Uint8()) { | 815 } else if (type == MachineType::Uint8()) { |
| 816 opcode = kExprI32AsmjsStoreMem8; | 816 opcode = kExprI32AsmjsStoreMem8; |
| 817 } else if (type == MachineType::Int16()) { | 817 } else if (type == MachineType::Int16()) { |
| 818 opcode = kExprI32AsmjsStoreMem16; | 818 opcode = kExprI32AsmjsStoreMem16; |
| 819 } else if (type == MachineType::Uint16()) { | 819 } else if (type == MachineType::Uint16()) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 839 | 839 |
| 840 void VisitAssignment(Assignment* expr) override { | 840 void VisitAssignment(Assignment* expr) override { |
| 841 bool as_init = false; | 841 bool as_init = false; |
| 842 if (scope_ == kModuleScope) { | 842 if (scope_ == kModuleScope) { |
| 843 Property* prop = expr->value()->AsProperty(); | 843 Property* prop = expr->value()->AsProperty(); |
| 844 if (prop != nullptr) { | 844 if (prop != nullptr) { |
| 845 VariableProxy* vp = prop->obj()->AsVariableProxy(); | 845 VariableProxy* vp = prop->obj()->AsVariableProxy(); |
| 846 if (vp != nullptr && vp->var()->IsParameter() && | 846 if (vp != nullptr && vp->var()->IsParameter() && |
| 847 vp->var()->index() == 1) { | 847 vp->var()->index() == 1) { |
| 848 VariableProxy* target = expr->target()->AsVariableProxy(); | 848 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 849 if (bounds_->get(target).lower->Is(Type::Function())) { | 849 if (typer_->TypeOf(target)->AsFFIType() != nullptr) { |
| 850 const AstRawString* name = | 850 const AstRawString* name = |
| 851 prop->key()->AsLiteral()->AsRawPropertyName(); | 851 prop->key()->AsLiteral()->AsRawPropertyName(); |
| 852 imported_function_table_.AddImport( | 852 imported_function_table_.AddImport( |
| 853 target->var(), reinterpret_cast<const char*>(name->raw_data()), | 853 target->var(), reinterpret_cast<const char*>(name->raw_data()), |
| 854 name->length()); | 854 name->length()); |
| 855 } | 855 } |
| 856 } | 856 } |
| 857 // Property values in module scope don't emit code, so return. | 857 // Property values in module scope don't emit code, so return. |
| 858 return; | 858 return; |
| 859 } | 859 } |
| 860 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); | 860 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
| 861 if (funcs != nullptr && | 861 if (funcs != nullptr && |
| 862 bounds_->get(funcs).lower->AsArray()->Element()->IsFunction()) { | 862 typer_->TypeOf(funcs) |
| 863 ->AsFunctionTableType() |
| 864 ->signature() |
| 865 ->AsFunctionType()) { |
| 863 VariableProxy* target = expr->target()->AsVariableProxy(); | 866 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 864 DCHECK_NOT_NULL(target); | 867 DCHECK_NOT_NULL(target); |
| 865 AddFunctionTable(target, funcs); | 868 AddFunctionTable(target, funcs); |
| 866 // Only add to the function table. No init needed. | 869 // Only add to the function table. No init needed. |
| 867 return; | 870 return; |
| 868 } | 871 } |
| 869 if (expr->value()->IsCallNew()) { | 872 if (expr->value()->IsCallNew()) { |
| 870 // No init code to emit for CallNew nodes. | 873 // No init code to emit for CallNew nodes. |
| 871 return; | 874 return; |
| 872 } | 875 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 898 if (!key_literal->value().is_null()) { | 901 if (!key_literal->value().is_null()) { |
| 899 Handle<Name> name = | 902 Handle<Name> name = |
| 900 i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked(); | 903 i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked(); |
| 901 LocalType type = is_float ? kAstF64 : kAstI32; | 904 LocalType type = is_float ? kAstF64 : kAstI32; |
| 902 foreign_variables_.push_back({name, var, type}); | 905 foreign_variables_.push_back({name, var, type}); |
| 903 } | 906 } |
| 904 } | 907 } |
| 905 | 908 |
| 906 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) { | 909 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) { |
| 907 Expression* obj = expr->obj(); | 910 Expression* obj = expr->obj(); |
| 908 DCHECK_EQ(bounds_->get(obj).lower, bounds_->get(obj).upper); | 911 AsmType* type = typer_->TypeOf(obj); |
| 909 Type* type = bounds_->get(obj).lower; | |
| 910 int size; | 912 int size; |
| 911 if (type->Is(cache_.kUint8Array)) { | 913 if (type->IsA(AsmType::Uint8Array())) { |
| 912 *mtype = MachineType::Uint8(); | 914 *mtype = MachineType::Uint8(); |
| 913 size = 1; | 915 size = 1; |
| 914 } else if (type->Is(cache_.kInt8Array)) { | 916 } else if (type->IsA(AsmType::Int8Array())) { |
| 915 *mtype = MachineType::Int8(); | 917 *mtype = MachineType::Int8(); |
| 916 size = 1; | 918 size = 1; |
| 917 } else if (type->Is(cache_.kUint16Array)) { | 919 } else if (type->IsA(AsmType::Uint16Array())) { |
| 918 *mtype = MachineType::Uint16(); | 920 *mtype = MachineType::Uint16(); |
| 919 size = 2; | 921 size = 2; |
| 920 } else if (type->Is(cache_.kInt16Array)) { | 922 } else if (type->IsA(AsmType::Int16Array())) { |
| 921 *mtype = MachineType::Int16(); | 923 *mtype = MachineType::Int16(); |
| 922 size = 2; | 924 size = 2; |
| 923 } else if (type->Is(cache_.kUint32Array)) { | 925 } else if (type->IsA(AsmType::Uint32Array())) { |
| 924 *mtype = MachineType::Uint32(); | 926 *mtype = MachineType::Uint32(); |
| 925 size = 4; | 927 size = 4; |
| 926 } else if (type->Is(cache_.kInt32Array)) { | 928 } else if (type->IsA(AsmType::Int32Array())) { |
| 927 *mtype = MachineType::Int32(); | 929 *mtype = MachineType::Int32(); |
| 928 size = 4; | 930 size = 4; |
| 929 } else if (type->Is(cache_.kUint32Array)) { | 931 } else if (type->IsA(AsmType::Uint32Array())) { |
| 930 *mtype = MachineType::Uint32(); | 932 *mtype = MachineType::Uint32(); |
| 931 size = 4; | 933 size = 4; |
| 932 } else if (type->Is(cache_.kFloat32Array)) { | 934 } else if (type->IsA(AsmType::Float32Array())) { |
| 933 *mtype = MachineType::Float32(); | 935 *mtype = MachineType::Float32(); |
| 934 size = 4; | 936 size = 4; |
| 935 } else if (type->Is(cache_.kFloat64Array)) { | 937 } else if (type->IsA(AsmType::Float64Array())) { |
| 936 *mtype = MachineType::Float64(); | 938 *mtype = MachineType::Float64(); |
| 937 size = 8; | 939 size = 8; |
| 938 } else { | 940 } else { |
| 939 UNREACHABLE(); | 941 UNREACHABLE(); |
| 940 } | 942 } |
| 941 if (size == 1) { | 943 if (size == 1) { |
| 942 // Allow more general expression in byte arrays than the spec | 944 // Allow more general expression in byte arrays than the spec |
| 943 // strictly permits. | 945 // strictly permits. |
| 944 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in | 946 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in |
| 945 // places that strictly should be HEAP8[HEAP32[..]>>0]. | 947 // places that strictly should be HEAP8[HEAP32[..]>>0]. |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1221 if (literal != nullptr) { | 1223 if (literal != nullptr) { |
| 1222 // constant fold Math.fround(#const); | 1224 // constant fold Math.fround(#const); |
| 1223 if (literal->raw_value()->IsNumber()) { | 1225 if (literal->raw_value()->IsNumber()) { |
| 1224 float val = static_cast<float>(literal->raw_value()->AsNumber()); | 1226 float val = static_cast<float>(literal->raw_value()->AsNumber()); |
| 1225 byte code[] = {WASM_F32(val)}; | 1227 byte code[] = {WASM_F32(val)}; |
| 1226 current_function_builder_->EmitCode(code, sizeof(code)); | 1228 current_function_builder_->EmitCode(code, sizeof(code)); |
| 1227 return true; | 1229 return true; |
| 1228 } | 1230 } |
| 1229 } | 1231 } |
| 1230 VisitCallArgs(call); | 1232 VisitCallArgs(call); |
| 1231 switch (TypeIndexOf(args->at(0))) { | 1233 static const bool kDontIgnoreSign = false; |
| 1234 switch (TypeIndexOf(args->at(0), kDontIgnoreSign)) { |
| 1232 case kInt32: | 1235 case kInt32: |
| 1233 case kFixnum: | 1236 case kFixnum: |
| 1234 current_function_builder_->Emit(kExprF32SConvertI32); | 1237 current_function_builder_->Emit(kExprF32SConvertI32); |
| 1235 break; | 1238 break; |
| 1236 case kUint32: | 1239 case kUint32: |
| 1237 current_function_builder_->Emit(kExprF32UConvertI32); | 1240 current_function_builder_->Emit(kExprF32UConvertI32); |
| 1238 break; | 1241 break; |
| 1239 case kFloat32: | 1242 case kFloat32: |
| 1240 break; | 1243 break; |
| 1241 case kFloat64: | 1244 case kFloat64: |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1268 case Call::OTHER_CALL: { | 1271 case Call::OTHER_CALL: { |
| 1269 DCHECK_EQ(kFuncScope, scope_); | 1272 DCHECK_EQ(kFuncScope, scope_); |
| 1270 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 1273 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 1271 if (proxy != nullptr) { | 1274 if (proxy != nullptr) { |
| 1272 if (VisitStdlibFunction(expr, proxy)) { | 1275 if (VisitStdlibFunction(expr, proxy)) { |
| 1273 return; | 1276 return; |
| 1274 } | 1277 } |
| 1275 } | 1278 } |
| 1276 uint32_t index; | 1279 uint32_t index; |
| 1277 VariableProxy* vp = expr->expression()->AsVariableProxy(); | 1280 VariableProxy* vp = expr->expression()->AsVariableProxy(); |
| 1278 if (vp != nullptr && | 1281 DCHECK_NOT_NULL(vp); |
| 1279 Type::Any()->Is(bounds_->get(vp).lower->AsFunction()->Result())) { | 1282 if (typer_->TypeOf(vp)->AsFFIType() != nullptr) { |
| 1280 LocalType return_type = TypeOf(expr); | 1283 LocalType return_type = TypeOf(expr); |
| 1281 ZoneList<Expression*>* args = expr->arguments(); | 1284 ZoneList<Expression*>* args = expr->arguments(); |
| 1282 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 1285 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 1283 args->length()); | 1286 args->length()); |
| 1284 if (return_type != kAstStmt) { | 1287 if (return_type != kAstStmt) { |
| 1285 sig.AddReturn(return_type); | 1288 sig.AddReturn(return_type); |
| 1286 } | 1289 } |
| 1287 for (int i = 0; i < args->length(); ++i) { | 1290 for (int i = 0; i < args->length(); ++i) { |
| 1288 sig.AddParam(TypeOf(args->at(i))); | 1291 sig.AddParam(TypeOf(args->at(i))); |
| 1289 } | 1292 } |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 Expression* GetLeft(BinaryOperation* expr) { | 1475 Expression* GetLeft(BinaryOperation* expr) { |
| 1473 if (expr->op() == Token::BIT_XOR) { | 1476 if (expr->op() == Token::BIT_XOR) { |
| 1474 return expr->left()->AsBinaryOperation()->left(); | 1477 return expr->left()->AsBinaryOperation()->left(); |
| 1475 } else { | 1478 } else { |
| 1476 return expr->left(); | 1479 return expr->left(); |
| 1477 } | 1480 } |
| 1478 } | 1481 } |
| 1479 | 1482 |
| 1480 void VisitBinaryOperation(BinaryOperation* expr) override { | 1483 void VisitBinaryOperation(BinaryOperation* expr) override { |
| 1481 ConvertOperation convertOperation = MatchBinaryOperation(expr); | 1484 ConvertOperation convertOperation = MatchBinaryOperation(expr); |
| 1485 static const bool kDontIgnoreSign = false; |
| 1482 if (convertOperation == kToDouble) { | 1486 if (convertOperation == kToDouble) { |
| 1483 RECURSE(Visit(expr->left())); | 1487 RECURSE(Visit(expr->left())); |
| 1484 TypeIndex type = TypeIndexOf(expr->left()); | 1488 TypeIndex type = TypeIndexOf(expr->left(), kDontIgnoreSign); |
| 1485 if (type == kInt32 || type == kFixnum) { | 1489 if (type == kInt32 || type == kFixnum) { |
| 1486 current_function_builder_->Emit(kExprF64SConvertI32); | 1490 current_function_builder_->Emit(kExprF64SConvertI32); |
| 1487 } else if (type == kUint32) { | 1491 } else if (type == kUint32) { |
| 1488 current_function_builder_->Emit(kExprF64UConvertI32); | 1492 current_function_builder_->Emit(kExprF64UConvertI32); |
| 1489 } else if (type == kFloat32) { | 1493 } else if (type == kFloat32) { |
| 1490 current_function_builder_->Emit(kExprF64ConvertF32); | 1494 current_function_builder_->Emit(kExprF64ConvertF32); |
| 1491 } else { | 1495 } else { |
| 1492 UNREACHABLE(); | 1496 UNREACHABLE(); |
| 1493 } | 1497 } |
| 1494 } else if (convertOperation == kToInt) { | 1498 } else if (convertOperation == kToInt) { |
| 1495 RECURSE(Visit(GetLeft(expr))); | 1499 RECURSE(Visit(GetLeft(expr))); |
| 1496 TypeIndex type = TypeIndexOf(GetLeft(expr)); | 1500 TypeIndex type = TypeIndexOf(GetLeft(expr), kDontIgnoreSign); |
| 1497 if (type == kFloat32) { | 1501 if (type == kFloat32) { |
| 1498 current_function_builder_->Emit(kExprI32AsmjsSConvertF32); | 1502 current_function_builder_->Emit(kExprI32AsmjsSConvertF32); |
| 1499 } else if (type == kFloat64) { | 1503 } else if (type == kFloat64) { |
| 1500 current_function_builder_->Emit(kExprI32AsmjsSConvertF64); | 1504 current_function_builder_->Emit(kExprI32AsmjsSConvertF64); |
| 1501 } else { | 1505 } else { |
| 1502 UNREACHABLE(); | 1506 UNREACHABLE(); |
| 1503 } | 1507 } |
| 1504 } else if (convertOperation == kAsIs) { | 1508 } else if (convertOperation == kAsIs) { |
| 1505 RECURSE(Visit(GetLeft(expr))); | 1509 RECURSE(Visit(GetLeft(expr))); |
| 1506 } else { | 1510 } else { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1576 | 1580 |
| 1577 enum TypeIndex { | 1581 enum TypeIndex { |
| 1578 kInt32 = 0, | 1582 kInt32 = 0, |
| 1579 kUint32 = 1, | 1583 kUint32 = 1, |
| 1580 kFloat32 = 2, | 1584 kFloat32 = 2, |
| 1581 kFloat64 = 3, | 1585 kFloat64 = 3, |
| 1582 kFixnum = 4 | 1586 kFixnum = 4 |
| 1583 }; | 1587 }; |
| 1584 | 1588 |
| 1585 TypeIndex TypeIndexOf(Expression* left, Expression* right, bool ignore_sign) { | 1589 TypeIndex TypeIndexOf(Expression* left, Expression* right, bool ignore_sign) { |
| 1586 TypeIndex left_index = TypeIndexOf(left); | 1590 TypeIndex left_index = TypeIndexOf(left, ignore_sign); |
| 1587 TypeIndex right_index = TypeIndexOf(right); | 1591 TypeIndex right_index = TypeIndexOf(right, ignore_sign); |
| 1588 if (left_index == kFixnum) { | 1592 if (left_index == kFixnum) { |
| 1589 left_index = right_index; | 1593 left_index = right_index; |
| 1590 } | 1594 } |
| 1591 if (right_index == kFixnum) { | 1595 if (right_index == kFixnum) { |
| 1592 right_index = left_index; | 1596 right_index = left_index; |
| 1593 } | 1597 } |
| 1594 if (left_index == kFixnum && right_index == kFixnum) { | 1598 if (left_index == kFixnum && right_index == kFixnum) { |
| 1595 left_index = kInt32; | 1599 left_index = kInt32; |
| 1596 right_index = kInt32; | 1600 right_index = kInt32; |
| 1597 } | 1601 } |
| 1598 DCHECK((left_index == right_index) || | 1602 if (left_index != right_index) { |
| 1599 (ignore_sign && (left_index <= 1) && (right_index <= 1))); | 1603 DCHECK(ignore_sign && (left_index <= 1) && (right_index <= 1)); |
| 1604 } |
| 1600 return left_index; | 1605 return left_index; |
| 1601 } | 1606 } |
| 1602 | 1607 |
| 1603 TypeIndex TypeIndexOf(Expression* expr) { | 1608 TypeIndex TypeIndexOf(Expression* expr, bool ignore_sign) { |
| 1604 DCHECK_EQ(bounds_->get(expr).lower, bounds_->get(expr).upper); | 1609 AsmType* type = typer_->TypeOf(expr); |
| 1605 Type* type = bounds_->get(expr).lower; | 1610 if (type->IsA(AsmType::FixNum())) { |
| 1606 if (type->Is(cache_.kAsmFixnum)) { | |
| 1607 return kFixnum; | 1611 return kFixnum; |
| 1608 } else if (type->Is(cache_.kAsmSigned)) { | 1612 } |
| 1609 return kInt32; | 1613 |
| 1610 } else if (type->Is(cache_.kAsmUnsigned)) { | 1614 if (type->IsA(AsmType::Signed())) { |
| 1611 return kUint32; | |
| 1612 } else if (type->Is(cache_.kAsmInt)) { | |
| 1613 return kInt32; | |
| 1614 } else if (type->Is(cache_.kAsmFloat)) { | |
| 1615 return kFloat32; | |
| 1616 } else if (type->Is(cache_.kAsmDouble)) { | |
| 1617 return kFloat64; | |
| 1618 } else { | |
| 1619 UNREACHABLE(); | |
| 1620 return kInt32; | 1615 return kInt32; |
| 1621 } | 1616 } |
| 1617 |
| 1618 if (type->IsA(AsmType::Unsigned())) { |
| 1619 return kUint32; |
| 1620 } |
| 1621 |
| 1622 if (type->IsA(AsmType::Intish())) { |
| 1623 if (!ignore_sign) { |
| 1624 // TODO(jpp): log a warning and move on. |
| 1625 } |
| 1626 return kInt32; |
| 1627 } |
| 1628 |
| 1629 if (type->IsA(AsmType::Floatish())) { |
| 1630 return kFloat32; |
| 1631 } |
| 1632 |
| 1633 if (type->IsA(AsmType::DoubleQ())) { |
| 1634 return kFloat64; |
| 1635 } |
| 1636 |
| 1637 UNREACHABLE(); |
| 1638 return kInt32; |
| 1622 } | 1639 } |
| 1623 | 1640 |
| 1624 #undef CASE | 1641 #undef CASE |
| 1625 #undef NON_SIGNED_INT | 1642 #undef NON_SIGNED_INT |
| 1626 #undef SIGNED | 1643 #undef SIGNED |
| 1627 #undef NON_SIGNED | 1644 #undef NON_SIGNED |
| 1628 | 1645 |
| 1629 void VisitThisFunction(ThisFunction* expr) override { UNREACHABLE(); } | 1646 void VisitThisFunction(ThisFunction* expr) override { UNREACHABLE(); } |
| 1630 | 1647 |
| 1631 void VisitDeclarations(ZoneList<Declaration*>* decls) override { | 1648 void VisitDeclarations(ZoneList<Declaration*>* decls) override { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1714 uint32_t index = builder_->AddFunction(); | 1731 uint32_t index = builder_->AddFunction(); |
| 1715 IndexContainer* container = new (zone()) IndexContainer(); | 1732 IndexContainer* container = new (zone()) IndexContainer(); |
| 1716 container->index = index; | 1733 container->index = index; |
| 1717 entry = functions_.LookupOrInsert(v, ComputePointerHash(v), | 1734 entry = functions_.LookupOrInsert(v, ComputePointerHash(v), |
| 1718 ZoneAllocationPolicy(zone())); | 1735 ZoneAllocationPolicy(zone())); |
| 1719 entry->value = container; | 1736 entry->value = container; |
| 1720 } | 1737 } |
| 1721 return (reinterpret_cast<IndexContainer*>(entry->value))->index; | 1738 return (reinterpret_cast<IndexContainer*>(entry->value))->index; |
| 1722 } | 1739 } |
| 1723 | 1740 |
| 1724 LocalType TypeOf(Expression* expr) { | 1741 LocalType TypeOf(Expression* expr) { return TypeFrom(typer_->TypeOf(expr)); } |
| 1725 DCHECK_EQ(bounds_->get(expr).lower, bounds_->get(expr).upper); | |
| 1726 return TypeFrom(bounds_->get(expr).lower); | |
| 1727 } | |
| 1728 | 1742 |
| 1729 LocalType TypeFrom(Type* type) { | 1743 LocalType TypeFrom(AsmType* type) { |
| 1730 if (type->Is(cache_.kAsmInt)) { | 1744 if (type->IsA(AsmType::Intish())) { |
| 1731 return kAstI32; | 1745 return kAstI32; |
| 1732 } else if (type->Is(cache_.kAsmFloat)) { | 1746 } |
| 1747 |
| 1748 if (type->IsA(AsmType::Floatish())) { |
| 1733 return kAstF32; | 1749 return kAstF32; |
| 1734 } else if (type->Is(cache_.kAsmDouble)) { | 1750 } |
| 1751 |
| 1752 if (type->IsA(AsmType::DoubleQ())) { |
| 1735 return kAstF64; | 1753 return kAstF64; |
| 1736 } else { | |
| 1737 return kAstStmt; | |
| 1738 } | 1754 } |
| 1755 |
| 1756 return kAstStmt; |
| 1739 } | 1757 } |
| 1740 | 1758 |
| 1741 Zone* zone() { return zone_; } | 1759 Zone* zone() { return zone_; } |
| 1742 | 1760 |
| 1743 ZoneHashMap local_variables_; | 1761 ZoneHashMap local_variables_; |
| 1744 ZoneHashMap functions_; | 1762 ZoneHashMap functions_; |
| 1745 ZoneHashMap global_variables_; | 1763 ZoneHashMap global_variables_; |
| 1746 AsmScope scope_; | 1764 AsmScope scope_; |
| 1747 WasmModuleBuilder* builder_; | 1765 WasmModuleBuilder* builder_; |
| 1748 WasmFunctionBuilder* current_function_builder_; | 1766 WasmFunctionBuilder* current_function_builder_; |
| 1749 FunctionLiteral* literal_; | 1767 FunctionLiteral* literal_; |
| 1750 Isolate* isolate_; | 1768 Isolate* isolate_; |
| 1751 Zone* zone_; | 1769 Zone* zone_; |
| 1752 AsmTyper* typer_; | 1770 AsmTyper* typer_; |
| 1753 TypeCache const& cache_; | |
| 1754 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1771 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
| 1755 ZoneVector<ForeignVariable> foreign_variables_; | 1772 ZoneVector<ForeignVariable> foreign_variables_; |
| 1756 uint32_t init_function_index_; | 1773 uint32_t init_function_index_; |
| 1757 uint32_t foreign_init_function_index_; | 1774 uint32_t foreign_init_function_index_; |
| 1758 uint32_t next_table_index_; | 1775 uint32_t next_table_index_; |
| 1759 ZoneHashMap function_tables_; | 1776 ZoneHashMap function_tables_; |
| 1760 ImportedFunctionTable imported_function_table_; | 1777 ImportedFunctionTable imported_function_table_; |
| 1761 const AstTypeBounds* bounds_; | |
| 1762 | 1778 |
| 1763 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1779 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
| 1764 | 1780 |
| 1765 private: | 1781 private: |
| 1766 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1782 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
| 1767 }; | 1783 }; |
| 1768 | 1784 |
| 1769 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, | 1785 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, |
| 1770 FunctionLiteral* literal, AsmTyper* typer) | 1786 FunctionLiteral* literal, AsmTyper* typer) |
| 1771 : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {} | 1787 : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {} |
| 1772 | 1788 |
| 1773 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so | 1789 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so |
| 1774 // that zone in constructor may be thrown away once wasm module is written. | 1790 // that zone in constructor may be thrown away once wasm module is written. |
| 1775 ZoneBuffer* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) { | 1791 ZoneBuffer* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) { |
| 1776 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_); | 1792 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_); |
| 1777 impl.Build(); | 1793 impl.Build(); |
| 1778 *foreign_args = impl.GetForeignArgs(); | 1794 *foreign_args = impl.GetForeignArgs(); |
| 1779 ZoneBuffer* buffer = new (zone_) ZoneBuffer(zone_); | 1795 ZoneBuffer* buffer = new (zone_) ZoneBuffer(zone_); |
| 1780 impl.builder_->WriteTo(*buffer); | 1796 impl.builder_->WriteTo(*buffer); |
| 1781 return buffer; | 1797 return buffer; |
| 1782 } | 1798 } |
| 1783 } // namespace wasm | 1799 } // namespace wasm |
| 1784 } // namespace internal | 1800 } // namespace internal |
| 1785 } // namespace v8 | 1801 } // namespace v8 |
| OLD | NEW |