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 |
(...skipping 18 matching lines...) Expand all Loading... | |
29 DCHECK(!HasStackOverflow()); \ | 29 DCHECK(!HasStackOverflow()); \ |
30 call; \ | 30 call; \ |
31 if (HasStackOverflow()) return; \ | 31 if (HasStackOverflow()) return; \ |
32 } while (false) | 32 } while (false) |
33 | 33 |
34 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; | 34 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; |
35 | 35 |
36 class AsmWasmBuilderImpl : public AstVisitor { | 36 class AsmWasmBuilderImpl : public AstVisitor { |
37 public: | 37 public: |
38 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, | 38 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, |
39 Handle<Object> foreign, AsmTyper* typer) | 39 AsmTyper* typer) |
40 : local_variables_(HashMap::PointersMatch, | 40 : local_variables_(HashMap::PointersMatch, |
41 ZoneHashMap::kDefaultHashMapCapacity, | 41 ZoneHashMap::kDefaultHashMapCapacity, |
42 ZoneAllocationPolicy(zone)), | 42 ZoneAllocationPolicy(zone)), |
43 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, | 43 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, |
44 ZoneAllocationPolicy(zone)), | 44 ZoneAllocationPolicy(zone)), |
45 global_variables_(HashMap::PointersMatch, | 45 global_variables_(HashMap::PointersMatch, |
46 ZoneHashMap::kDefaultHashMapCapacity, | 46 ZoneHashMap::kDefaultHashMapCapacity, |
47 ZoneAllocationPolicy(zone)), | 47 ZoneAllocationPolicy(zone)), |
48 scope_(kModuleScope), | 48 scope_(kModuleScope), |
49 builder_(new (zone) WasmModuleBuilder(zone)), | 49 builder_(new (zone) WasmModuleBuilder(zone)), |
50 current_function_builder_(nullptr), | 50 current_function_builder_(nullptr), |
51 literal_(literal), | 51 literal_(literal), |
52 isolate_(isolate), | 52 isolate_(isolate), |
53 zone_(zone), | 53 zone_(zone), |
54 foreign_(foreign), | |
55 typer_(typer), | 54 typer_(typer), |
56 cache_(TypeCache::Get()), | 55 cache_(TypeCache::Get()), |
57 breakable_blocks_(zone), | 56 breakable_blocks_(zone), |
57 foreign_variables_(zone), | |
58 init_function_index_(0), | 58 init_function_index_(0), |
59 foreign_init_function_index_(0), | |
59 next_table_index_(0), | 60 next_table_index_(0), |
60 function_tables_(HashMap::PointersMatch, | 61 function_tables_(HashMap::PointersMatch, |
61 ZoneHashMap::kDefaultHashMapCapacity, | 62 ZoneHashMap::kDefaultHashMapCapacity, |
62 ZoneAllocationPolicy(zone)), | 63 ZoneAllocationPolicy(zone)), |
63 imported_function_table_(this), | 64 imported_function_table_(this), |
64 bounds_(typer->bounds()) { | 65 bounds_(typer->bounds()) { |
65 InitializeAstVisitor(isolate); | 66 InitializeAstVisitor(isolate); |
66 } | 67 } |
67 | 68 |
68 void InitializeInitFunction() { | 69 void InitializeInitFunction() { |
69 init_function_index_ = builder_->AddFunction(); | 70 init_function_index_ = builder_->AddFunction(); |
70 FunctionSig::Builder b(zone(), 0, 0); | 71 FunctionSig::Builder b(zone(), 0, 0); |
71 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 72 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
72 current_function_builder_->SetSignature(b.Build()); | 73 current_function_builder_->SetSignature(b.Build()); |
73 builder_->MarkStartFunction(init_function_index_); | 74 builder_->MarkStartFunction(init_function_index_); |
74 current_function_builder_ = nullptr; | 75 current_function_builder_ = nullptr; |
75 } | 76 } |
76 | 77 |
78 void BuildForeignInitFunction() { | |
79 foreign_init_function_index_ = builder_->AddFunction(); | |
80 FunctionSig::Builder b(zone(), 0, foreign_variables_.size()); | |
81 for (auto i = foreign_variables_.begin(); i != foreign_variables_.end(); | |
82 ++i) { | |
83 if (i->is_float) { | |
84 b.AddParam(kAstF64); | |
85 } else { | |
86 b.AddParam(kAstI32); | |
87 } | |
88 } | |
89 current_function_builder_ = | |
90 builder_->FunctionAt(foreign_init_function_index_); | |
91 current_function_builder_->Exported(1); | |
92 std::string raw_name = "__foreign_init__"; | |
93 current_function_builder_->SetName(raw_name.data(), | |
94 static_cast<int>(raw_name.size())); | |
95 current_function_builder_->SetSignature(b.Build()); | |
96 for (size_t pos = 0; pos < foreign_variables_.size(); ++pos) { | |
97 current_function_builder_->EmitGetLocal(static_cast<uint32_t>(pos)); | |
98 ForeignVariable* fv = &foreign_variables_[pos]; | |
99 LocalType var_type = fv->is_float ? kAstF64 : kAstI32; | |
100 uint32_t index = LookupOrInsertGlobal(fv->var, var_type); | |
101 current_function_builder_->EmitWithVarInt(kExprStoreGlobal, index); | |
102 } | |
103 current_function_builder_ = nullptr; | |
104 } | |
105 | |
106 i::Handle<i::FixedArray> GetForeignArgs() { | |
107 i::Handle<FixedArray> ret = isolate_->factory()->NewFixedArray( | |
108 static_cast<int>(foreign_variables_.size())); | |
109 for (size_t i = 0; i < foreign_variables_.size(); ++i) { | |
110 ForeignVariable* fv = &foreign_variables_[i]; | |
111 ret->set(static_cast<int>(i), *fv->name); | |
112 } | |
113 return ret; | |
114 } | |
115 | |
77 void Compile() { | 116 void Compile() { |
78 InitializeInitFunction(); | 117 InitializeInitFunction(); |
79 RECURSE(VisitFunctionLiteral(literal_)); | 118 RECURSE(VisitFunctionLiteral(literal_)); |
119 BuildForeignInitFunction(); | |
80 } | 120 } |
81 | 121 |
82 void VisitVariableDeclaration(VariableDeclaration* decl) {} | 122 void VisitVariableDeclaration(VariableDeclaration* decl) {} |
83 | 123 |
84 void VisitFunctionDeclaration(FunctionDeclaration* decl) { | 124 void VisitFunctionDeclaration(FunctionDeclaration* decl) { |
85 DCHECK_EQ(kModuleScope, scope_); | 125 DCHECK_EQ(kModuleScope, scope_); |
86 DCHECK_NULL(current_function_builder_); | 126 DCHECK_NULL(current_function_builder_); |
87 uint32_t index = LookupOrInsertFunction(decl->proxy()->var()); | 127 uint32_t index = LookupOrInsertFunction(decl->proxy()->var()); |
88 current_function_builder_ = builder_->FunctionAt(index); | 128 current_function_builder_ = builder_->FunctionAt(index); |
89 scope_ = kFuncScope; | 129 scope_ = kFuncScope; |
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
699 void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) { | 739 void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) { |
700 BinaryOperation* binop = value->AsBinaryOperation(); | 740 BinaryOperation* binop = value->AsBinaryOperation(); |
701 if (binop != nullptr) { | 741 if (binop != nullptr) { |
702 if (scope_ == kInitScope) { | 742 if (scope_ == kInitScope) { |
703 // Handle foreign variables in the initialization scope. | 743 // Handle foreign variables in the initialization scope. |
704 Property* prop = binop->left()->AsProperty(); | 744 Property* prop = binop->left()->AsProperty(); |
705 if (binop->op() == Token::MUL) { | 745 if (binop->op() == Token::MUL) { |
706 DCHECK(binop->right()->IsLiteral()); | 746 DCHECK(binop->right()->IsLiteral()); |
707 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); | 747 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); |
708 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); | 748 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
709 VisitForeignVariable(true, prop); | 749 DCHECK(target->IsVariableProxy()); |
750 VisitForeignVariable(true, target->AsVariableProxy()->var(), prop); | |
751 *is_nop = true; | |
710 return; | 752 return; |
711 } else if (binop->op() == Token::BIT_OR) { | 753 } else if (binop->op() == Token::BIT_OR) { |
712 DCHECK(binop->right()->IsLiteral()); | 754 DCHECK(binop->right()->IsLiteral()); |
713 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); | 755 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); |
714 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); | 756 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
715 VisitForeignVariable(false, prop); | 757 DCHECK(target->IsVariableProxy()); |
758 VisitForeignVariable(false, target->AsVariableProxy()->var(), prop); | |
759 *is_nop = true; | |
716 return; | 760 return; |
717 } else { | 761 } else { |
718 UNREACHABLE(); | 762 UNREACHABLE(); |
719 } | 763 } |
720 } | 764 } |
721 if (MatchBinaryOperation(binop) == kAsIs) { | 765 if (MatchBinaryOperation(binop) == kAsIs) { |
722 VariableProxy* target_var = target->AsVariableProxy(); | 766 VariableProxy* target_var = target->AsVariableProxy(); |
723 VariableProxy* effective_value_var = GetLeft(binop)->AsVariableProxy(); | 767 VariableProxy* effective_value_var = GetLeft(binop)->AsVariableProxy(); |
724 if (target_var != nullptr && effective_value_var != nullptr && | 768 if (target_var != nullptr && effective_value_var != nullptr && |
725 target_var->var() == effective_value_var->var()) { | 769 target_var->var() == effective_value_var->var()) { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
828 if (!is_nop) { | 872 if (!is_nop) { |
829 EmitAssignment(expr, mtype); | 873 EmitAssignment(expr, mtype); |
830 } | 874 } |
831 if (as_init) UnLoadInitFunction(); | 875 if (as_init) UnLoadInitFunction(); |
832 } | 876 } |
833 | 877 |
834 void VisitYield(Yield* expr) { UNREACHABLE(); } | 878 void VisitYield(Yield* expr) { UNREACHABLE(); } |
835 | 879 |
836 void VisitThrow(Throw* expr) { UNREACHABLE(); } | 880 void VisitThrow(Throw* expr) { UNREACHABLE(); } |
837 | 881 |
838 void VisitForeignVariable(bool is_float, Property* expr) { | 882 void VisitForeignVariable(bool is_float, Variable* var, Property* expr) { |
839 DCHECK(expr->obj()->AsVariableProxy()); | 883 DCHECK(expr->obj()->AsVariableProxy()); |
840 DCHECK(VariableLocation::PARAMETER == | 884 DCHECK(VariableLocation::PARAMETER == |
841 expr->obj()->AsVariableProxy()->var()->location()); | 885 expr->obj()->AsVariableProxy()->var()->location()); |
842 DCHECK_EQ(1, expr->obj()->AsVariableProxy()->var()->index()); | 886 DCHECK_EQ(1, expr->obj()->AsVariableProxy()->var()->index()); |
843 Literal* key_literal = expr->key()->AsLiteral(); | 887 Literal* key_literal = expr->key()->AsLiteral(); |
844 DCHECK_NOT_NULL(key_literal); | 888 DCHECK_NOT_NULL(key_literal); |
845 if (!key_literal->value().is_null() && !foreign_.is_null() && | 889 if (!key_literal->value().is_null()) { |
846 foreign_->IsObject()) { | |
847 Handle<Name> name = | 890 Handle<Name> name = |
848 i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked(); | 891 i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked(); |
849 MaybeHandle<Object> maybe_value = i::Object::GetProperty(foreign_, name); | 892 ForeignVariable foreign; |
850 if (!maybe_value.is_null()) { | 893 foreign.name = name; |
851 Handle<Object> value = maybe_value.ToHandleChecked(); | 894 foreign.var = var; |
852 if (is_float) { | 895 foreign.is_float = is_float; |
853 MaybeHandle<Object> maybe_nvalue = i::Object::ToNumber(value); | 896 foreign_variables_.push_back(foreign); |
titzer
2016/05/20 11:39:59
Could you just do push_back({...})?
bradn
2016/05/20 14:37:32
Done.
| |
854 if (!maybe_nvalue.is_null()) { | |
855 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); | |
856 if (nvalue->IsNumber()) { | |
857 double val = nvalue->Number(); | |
858 byte code[] = {WASM_F64(val)}; | |
859 current_function_builder_->EmitCode(code, sizeof(code)); | |
860 return; | |
861 } | |
862 } | |
863 } else { | |
864 MaybeHandle<Object> maybe_nvalue = | |
865 i::Object::ToInt32(isolate_, value); | |
866 if (!maybe_nvalue.is_null()) { | |
867 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); | |
868 if (nvalue->IsNumber()) { | |
869 int32_t val = static_cast<int32_t>(nvalue->Number()); | |
870 current_function_builder_->EmitI32Const(val); | |
871 return; | |
872 } | |
873 } | |
874 } | |
875 } | |
876 } | |
877 if (is_float) { | |
878 byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())}; | |
879 current_function_builder_->EmitCode(code, sizeof(code)); | |
880 } else { | |
881 byte code[] = {WASM_I32V_1(0)}; | |
882 current_function_builder_->EmitCode(code, sizeof(code)); | |
883 } | 897 } |
884 } | 898 } |
885 | 899 |
886 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) { | 900 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) { |
887 Expression* obj = expr->obj(); | 901 Expression* obj = expr->obj(); |
888 DCHECK_EQ(bounds_->get(obj).lower, bounds_->get(obj).upper); | 902 DCHECK_EQ(bounds_->get(obj).lower, bounds_->get(obj).upper); |
889 Type* type = bounds_->get(obj).lower; | 903 Type* type = bounds_->get(obj).lower; |
890 int size; | 904 int size; |
891 if (type->Is(cache_.kUint8Array)) { | 905 if (type->Is(cache_.kUint8Array)) { |
892 *mtype = MachineType::Uint8(); | 906 *mtype = MachineType::Uint8(); |
(...skipping 813 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1706 return kAstI32; | 1720 return kAstI32; |
1707 } else if (type->Is(cache_.kAsmFloat)) { | 1721 } else if (type->Is(cache_.kAsmFloat)) { |
1708 return kAstF32; | 1722 return kAstF32; |
1709 } else if (type->Is(cache_.kAsmDouble)) { | 1723 } else if (type->Is(cache_.kAsmDouble)) { |
1710 return kAstF64; | 1724 return kAstF64; |
1711 } else { | 1725 } else { |
1712 return kAstStmt; | 1726 return kAstStmt; |
1713 } | 1727 } |
1714 } | 1728 } |
1715 | 1729 |
1730 struct ForeignVariable { | |
titzer
2016/05/20 11:39:59
Can you move this to the top?
bradn
2016/05/20 14:37:32
Done.
| |
1731 Variable* var; | |
1732 Handle<Name> name; | |
1733 bool is_float; | |
titzer
2016/05/20 11:39:59
Should we store the AST type here instead of a boo
bradn
2016/05/20 14:37:32
Done.
| |
1734 }; | |
1735 | |
1716 Zone* zone() { return zone_; } | 1736 Zone* zone() { return zone_; } |
1717 | 1737 |
1718 ZoneHashMap local_variables_; | 1738 ZoneHashMap local_variables_; |
1719 ZoneHashMap functions_; | 1739 ZoneHashMap functions_; |
1720 ZoneHashMap global_variables_; | 1740 ZoneHashMap global_variables_; |
1721 AsmScope scope_; | 1741 AsmScope scope_; |
1722 WasmModuleBuilder* builder_; | 1742 WasmModuleBuilder* builder_; |
1723 WasmFunctionBuilder* current_function_builder_; | 1743 WasmFunctionBuilder* current_function_builder_; |
1724 FunctionLiteral* literal_; | 1744 FunctionLiteral* literal_; |
1725 Isolate* isolate_; | 1745 Isolate* isolate_; |
1726 Zone* zone_; | 1746 Zone* zone_; |
1727 Handle<Object> foreign_; | |
1728 AsmTyper* typer_; | 1747 AsmTyper* typer_; |
1729 TypeCache const& cache_; | 1748 TypeCache const& cache_; |
1730 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1749 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
1750 ZoneVector<ForeignVariable> foreign_variables_; | |
1731 uint32_t init_function_index_; | 1751 uint32_t init_function_index_; |
1752 uint32_t foreign_init_function_index_; | |
1732 uint32_t next_table_index_; | 1753 uint32_t next_table_index_; |
1733 ZoneHashMap function_tables_; | 1754 ZoneHashMap function_tables_; |
1734 ImportedFunctionTable imported_function_table_; | 1755 ImportedFunctionTable imported_function_table_; |
1735 const AstTypeBounds* bounds_; | 1756 const AstTypeBounds* bounds_; |
1736 | 1757 |
1737 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1758 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
1738 | 1759 |
1739 private: | 1760 private: |
1740 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1761 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
1741 }; | 1762 }; |
1742 | 1763 |
1743 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, | 1764 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, |
1744 FunctionLiteral* literal, Handle<Object> foreign, | 1765 FunctionLiteral* literal, AsmTyper* typer) |
1745 AsmTyper* typer) | 1766 : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {} |
1746 : isolate_(isolate), | |
1747 zone_(zone), | |
1748 literal_(literal), | |
1749 foreign_(foreign), | |
1750 typer_(typer) {} | |
1751 | 1767 |
1752 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so | 1768 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so |
1753 // that zone in constructor may be thrown away once wasm module is written. | 1769 // that zone in constructor may be thrown away once wasm module is written. |
1754 WasmModuleIndex* AsmWasmBuilder::Run() { | 1770 WasmModuleIndex* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) { |
1755 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); | 1771 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_); |
1756 impl.Compile(); | 1772 impl.Compile(); |
1773 *foreign_args = impl.GetForeignArgs(); | |
1757 WasmModuleWriter* writer = impl.builder_->Build(zone_); | 1774 WasmModuleWriter* writer = impl.builder_->Build(zone_); |
1758 return writer->WriteTo(zone_); | 1775 return writer->WriteTo(zone_); |
1759 } | 1776 } |
1760 } // namespace wasm | 1777 } // namespace wasm |
1761 } // namespace internal | 1778 } // namespace internal |
1762 } // namespace v8 | 1779 } // namespace v8 |
OLD | NEW |