Chromium Code Reviews| 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 |