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 |