OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/asmjs/asm-typer.h" | 5 #include "src/asmjs/asm-typer.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "src/v8.h" | 10 #include "src/v8.h" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 continue; | 85 continue; |
86 } | 86 } |
87 | 87 |
88 return current_statement; | 88 return current_statement; |
89 } | 89 } |
90 } | 90 } |
91 | 91 |
92 // ---------------------------------------------------------------------------- | 92 // ---------------------------------------------------------------------------- |
93 // Implementation of AsmTyper::VariableInfo | 93 // Implementation of AsmTyper::VariableInfo |
94 | 94 |
| 95 AsmTyper::VariableInfo* AsmTyper::VariableInfo::ForSpecialSymbol( |
| 96 Zone* zone, StandardMember standard_member) { |
| 97 DCHECK(standard_member == kStdlib || standard_member == kFFI || |
| 98 standard_member == kHeap || standard_member == kModule); |
| 99 auto* new_var_info = new (zone) VariableInfo(AsmType::None()); |
| 100 new_var_info->standard_member_ = standard_member; |
| 101 new_var_info->mutability_ = kImmutableGlobal; |
| 102 return new_var_info; |
| 103 } |
| 104 |
95 AsmTyper::VariableInfo* AsmTyper::VariableInfo::Clone(Zone* zone) const { | 105 AsmTyper::VariableInfo* AsmTyper::VariableInfo::Clone(Zone* zone) const { |
96 CHECK(standard_member_ != kNone); | 106 CHECK(standard_member_ != kNone); |
| 107 CHECK(!type_->IsA(AsmType::None())); |
97 auto* new_var_info = new (zone) VariableInfo(type_); | 108 auto* new_var_info = new (zone) VariableInfo(type_); |
98 new_var_info->standard_member_ = standard_member_; | 109 new_var_info->standard_member_ = standard_member_; |
99 new_var_info->mutability_ = mutability_; | 110 new_var_info->mutability_ = mutability_; |
100 return new_var_info; | 111 return new_var_info; |
101 } | 112 } |
102 | 113 |
103 void AsmTyper::VariableInfo::FirstForwardUseIs(VariableProxy* var) { | 114 void AsmTyper::VariableInfo::FirstForwardUseIs(VariableProxy* var) { |
104 DCHECK(first_forward_use_ == nullptr); | 115 DCHECK(first_forward_use_ == nullptr); |
105 missing_definition_ = true; | 116 missing_definition_ = true; |
106 first_forward_use_ = var; | 117 first_forward_use_ = var; |
107 } | 118 } |
108 | 119 |
109 // ---------------------------------------------------------------------------- | 120 // ---------------------------------------------------------------------------- |
110 // Implementation of AsmTyper | 121 // Implementation of AsmTyper |
111 | 122 |
112 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, | 123 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, |
113 FunctionLiteral* root) | 124 FunctionLiteral* root) |
114 : isolate_(isolate), | 125 : isolate_(isolate), |
115 zone_(zone), | 126 zone_(zone), |
116 script_(script), | 127 script_(script), |
117 root_(root), | 128 root_(root), |
118 forward_definitions_(zone), | 129 forward_definitions_(zone), |
119 stdlib_types_(zone), | 130 stdlib_types_(zone), |
120 stdlib_math_types_(zone), | 131 stdlib_math_types_(zone), |
| 132 module_info_(VariableInfo::ForSpecialSymbol(zone_, kModule)), |
121 global_scope_(ZoneHashMap::PointersMatch, | 133 global_scope_(ZoneHashMap::PointersMatch, |
122 ZoneHashMap::kDefaultHashMapCapacity, | 134 ZoneHashMap::kDefaultHashMapCapacity, |
123 ZoneAllocationPolicy(zone)), | 135 ZoneAllocationPolicy(zone)), |
124 local_scope_(ZoneHashMap::PointersMatch, | 136 local_scope_(ZoneHashMap::PointersMatch, |
125 ZoneHashMap::kDefaultHashMapCapacity, | 137 ZoneHashMap::kDefaultHashMapCapacity, |
126 ZoneAllocationPolicy(zone)), | 138 ZoneAllocationPolicy(zone)), |
127 stack_limit_(isolate->stack_guard()->real_climit()), | 139 stack_limit_(isolate->stack_guard()->real_climit()), |
128 node_types_(zone_), | 140 node_types_(zone_), |
129 fround_type_(AsmType::FroundType(zone_)) { | 141 fround_type_(AsmType::FroundType(zone_)), |
| 142 ffi_type_(AsmType::FFIType(zone_)) { |
130 InitializeStdlib(); | 143 InitializeStdlib(); |
131 module_info_.set_standard_member(kModule); | |
132 } | 144 } |
133 | 145 |
134 namespace { | 146 namespace { |
135 bool ValidAsmIdentifier(Handle<String> name) { | 147 bool ValidAsmIdentifier(Handle<String> name) { |
136 static const char* kInvalidAsmNames[] = {"eval", "arguments"}; | 148 static const char* kInvalidAsmNames[] = {"eval", "arguments"}; |
137 | 149 |
138 for (size_t ii = 0; ii < arraysize(kInvalidAsmNames); ++ii) { | 150 for (size_t ii = 0; ii < arraysize(kInvalidAsmNames); ++ii) { |
139 if (strcmp(name->ToCString().get(), kInvalidAsmNames[ii]) == 0) { | 151 if (strcmp(name->ToCString().get(), kInvalidAsmNames[ii]) == 0) { |
140 return false; | 152 return false; |
141 } | 153 } |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 AsmTyper::VariableInfo* AsmTyper::Lookup(Variable* variable) { | 323 AsmTyper::VariableInfo* AsmTyper::Lookup(Variable* variable) { |
312 ZoneHashMap* scope = in_function_ ? &local_scope_ : &global_scope_; | 324 ZoneHashMap* scope = in_function_ ? &local_scope_ : &global_scope_; |
313 ZoneHashMap::Entry* entry = | 325 ZoneHashMap::Entry* entry = |
314 scope->Lookup(variable, ComputePointerHash(variable)); | 326 scope->Lookup(variable, ComputePointerHash(variable)); |
315 if (entry == nullptr && in_function_) { | 327 if (entry == nullptr && in_function_) { |
316 entry = global_scope_.Lookup(variable, ComputePointerHash(variable)); | 328 entry = global_scope_.Lookup(variable, ComputePointerHash(variable)); |
317 } | 329 } |
318 | 330 |
319 if (entry == nullptr && !module_name_.is_null() && | 331 if (entry == nullptr && !module_name_.is_null() && |
320 module_name_->Equals(*variable->name())) { | 332 module_name_->Equals(*variable->name())) { |
321 return &module_info_; | 333 return module_info_; |
322 } | 334 } |
323 | 335 |
324 return entry ? reinterpret_cast<VariableInfo*>(entry->value) : nullptr; | 336 return entry ? reinterpret_cast<VariableInfo*>(entry->value) : nullptr; |
325 } | 337 } |
326 | 338 |
327 void AsmTyper::AddForwardReference(VariableProxy* proxy, VariableInfo* info) { | 339 void AsmTyper::AddForwardReference(VariableProxy* proxy, VariableInfo* info) { |
328 info->FirstForwardUseIs(proxy); | 340 info->FirstForwardUseIs(proxy); |
329 forward_definitions_.push_back(info); | 341 forward_definitions_.push_back(info); |
330 } | 342 } |
331 | 343 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 module_name_ = fun->name(); | 474 module_name_ = fun->name(); |
463 | 475 |
464 // Allowed parameters: Stdlib, FFI, Mem | 476 // Allowed parameters: Stdlib, FFI, Mem |
465 static const uint32_t MaxModuleParameters = 3; | 477 static const uint32_t MaxModuleParameters = 3; |
466 if (scope->num_parameters() > MaxModuleParameters) { | 478 if (scope->num_parameters() > MaxModuleParameters) { |
467 FAIL(fun, "asm.js modules may not have more than three parameters."); | 479 FAIL(fun, "asm.js modules may not have more than three parameters."); |
468 } | 480 } |
469 | 481 |
470 struct { | 482 struct { |
471 StandardMember standard_member; | 483 StandardMember standard_member; |
472 AsmType* type; | |
473 } kModuleParamInfo[3] = { | 484 } kModuleParamInfo[3] = { |
474 {kStdlib, AsmType::None()}, | 485 {kStdlib}, {kFFI}, {kHeap}, |
475 {kFFI, AsmType::FFIType(zone_)}, | |
476 {kHeap, AsmType::None()}, | |
477 }; | 486 }; |
478 | 487 |
479 for (int ii = 0; ii < scope->num_parameters(); ++ii) { | 488 for (int ii = 0; ii < scope->num_parameters(); ++ii) { |
480 Variable* param = scope->parameter(ii); | 489 Variable* param = scope->parameter(ii); |
481 DCHECK(param); | 490 DCHECK(param); |
482 | 491 |
483 if (!ValidAsmIdentifier(param->name())) { | 492 if (!ValidAsmIdentifier(param->name())) { |
484 FAIL(fun, "Invalid asm.js identifier in module parameter."); | 493 FAIL(fun, "Invalid asm.js identifier in module parameter."); |
485 } | 494 } |
486 | 495 |
487 auto* param_info = new (zone_) VariableInfo(); | 496 auto* param_info = VariableInfo::ForSpecialSymbol( |
488 param_info->set_mutability(VariableInfo::kImmutableGlobal); | 497 zone_, kModuleParamInfo[ii].standard_member); |
489 param_info->set_standard_member(kModuleParamInfo[ii].standard_member); | |
490 param_info->set_type(kModuleParamInfo[ii].type); | |
491 | 498 |
492 if (!AddGlobal(param, param_info)) { | 499 if (!AddGlobal(param, param_info)) { |
493 FAIL(fun, "Redeclared identifier in module parameter."); | 500 FAIL(fun, "Redeclared identifier in module parameter."); |
494 } | 501 } |
495 } | 502 } |
496 | 503 |
497 ZoneVector<Assignment*> function_pointer_tables(zone_); | 504 ZoneVector<Assignment*> function_pointer_tables(zone_); |
498 FlattenedStatements iter(zone_, fun->body()); | 505 FlattenedStatements iter(zone_, fun->body()); |
499 auto* use_asm_directive = iter.Next(); | 506 auto* use_asm_directive = iter.Next(); |
500 if (use_asm_directive == nullptr || !IsUseAsmDirective(use_asm_directive)) { | 507 if (use_asm_directive == nullptr || !IsUseAsmDirective(use_asm_directive)) { |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 } else if (value->IsProperty()) { | 651 } else if (value->IsProperty()) { |
645 target_info = ImportLookup(value->AsProperty()); | 652 target_info = ImportLookup(value->AsProperty()); |
646 if (target_info == nullptr) { | 653 if (target_info == nullptr) { |
647 FAIL(assign, "Invalid import."); | 654 FAIL(assign, "Invalid import."); |
648 } | 655 } |
649 CHECK(target_info->mutability() == VariableInfo::kImmutableGlobal); | 656 CHECK(target_info->mutability() == VariableInfo::kImmutableGlobal); |
650 if (!target_info->IsFFI()) { | 657 if (!target_info->IsFFI()) { |
651 target_info = target_info->Clone(zone_); | 658 target_info = target_info->Clone(zone_); |
652 } else { | 659 } else { |
653 // create a new target info that represents a foreign variable. | 660 // create a new target info that represents a foreign variable. |
654 DCHECK(target_info->type()->AsFFIType() != nullptr); | 661 target_info = new (zone_) VariableInfo(ffi_type_); |
655 target_info = new (zone_) VariableInfo(target_info->type()); | |
656 target_info->set_mutability(VariableInfo::kImmutableGlobal); | 662 target_info->set_mutability(VariableInfo::kImmutableGlobal); |
657 } | 663 } |
658 } else if (value->IsBinaryOperation()) { | 664 } else if (value->IsBinaryOperation()) { |
659 // This should either be: | 665 // This should either be: |
660 // | 666 // |
661 // var <> = ffi.<>|0 | 667 // var <> = ffi.<>|0 |
662 // | 668 // |
663 // or | 669 // or |
664 // | 670 // |
665 // var <> = +ffi.<> | 671 // var <> = +ffi.<> |
(...skipping 22 matching lines...) Expand all Loading... |
688 FAIL(value, | 694 FAIL(value, |
689 "Invalid initializer for foreign import - object lookup failed."); | 695 "Invalid initializer for foreign import - object lookup failed."); |
690 } | 696 } |
691 CHECK(target_info->mutability() == VariableInfo::kImmutableGlobal); | 697 CHECK(target_info->mutability() == VariableInfo::kImmutableGlobal); |
692 if (!target_info->IsFFI()) { | 698 if (!target_info->IsFFI()) { |
693 FAIL(value, | 699 FAIL(value, |
694 "Invalid initializer for foreign import - object is not the ffi."); | 700 "Invalid initializer for foreign import - object is not the ffi."); |
695 } | 701 } |
696 | 702 |
697 // Create a new target info that represents the foreign import. | 703 // Create a new target info that represents the foreign import. |
698 DCHECK(target_info->type()->AsFFIType() != nullptr); | |
699 target_info = new (zone_) VariableInfo(import_type); | 704 target_info = new (zone_) VariableInfo(import_type); |
700 target_info->set_mutability(VariableInfo::kMutableGlobal); | 705 target_info->set_mutability(VariableInfo::kMutableGlobal); |
701 } else if (value->IsCallNew()) { | 706 } else if (value->IsCallNew()) { |
702 AsmType* type = nullptr; | 707 AsmType* type = nullptr; |
703 RECURSE(type = NewHeapView(value->AsCallNew())); | 708 RECURSE(type = NewHeapView(value->AsCallNew())); |
704 target_info = new (zone_) VariableInfo(type); | 709 target_info = new (zone_) VariableInfo(type); |
705 target_info->set_mutability(VariableInfo::kImmutableGlobal); | 710 target_info->set_mutability(VariableInfo::kImmutableGlobal); |
706 } | 711 } |
707 | 712 |
708 if (target_info == nullptr) { | 713 if (target_info == nullptr) { |
(...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1544 | 1549 |
1545 return AsmType::Unsigned(); | 1550 return AsmType::Unsigned(); |
1546 } | 1551 } |
1547 | 1552 |
1548 // 6.8.3 Identifier | 1553 // 6.8.3 Identifier |
1549 AsmType* AsmTyper::ValidateIdentifier(VariableProxy* proxy) { | 1554 AsmType* AsmTyper::ValidateIdentifier(VariableProxy* proxy) { |
1550 auto* proxy_info = Lookup(proxy->var()); | 1555 auto* proxy_info = Lookup(proxy->var()); |
1551 if (proxy_info == nullptr) { | 1556 if (proxy_info == nullptr) { |
1552 FAIL(proxy, "Undeclared identifier."); | 1557 FAIL(proxy, "Undeclared identifier."); |
1553 } | 1558 } |
1554 if (proxy_info->type()->AsCallableType() != nullptr) { | 1559 auto* type = proxy_info->type(); |
| 1560 if (type->IsA(AsmType::None()) || type->AsCallableType() != nullptr) { |
1555 FAIL(proxy, "Identifier may not be accessed by ordinary expressions."); | 1561 FAIL(proxy, "Identifier may not be accessed by ordinary expressions."); |
1556 } | 1562 } |
1557 DCHECK(!proxy_info->type()->IsA(AsmType::None())); | 1563 return type; |
1558 return proxy_info->type(); | |
1559 } | 1564 } |
1560 | 1565 |
1561 // 6.8.4 CallExpression | 1566 // 6.8.4 CallExpression |
1562 AsmType* AsmTyper::ValidateCallExpression(Call* call) { | 1567 AsmType* AsmTyper::ValidateCallExpression(Call* call) { |
1563 AsmType* return_type; | 1568 AsmType* return_type; |
1564 RECURSE(return_type = ValidateFloatCoercion(call)); | 1569 RECURSE(return_type = ValidateFloatCoercion(call)); |
1565 if (return_type == nullptr) { | 1570 if (return_type == nullptr) { |
1566 FAIL(call, "Unanotated call to a function must be a call to fround."); | 1571 FAIL(call, "Unanotated call to a function must be a call to fround."); |
1567 } | 1572 } |
1568 return return_type; | 1573 return return_type; |
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2621 return true; | 2626 return true; |
2622 } | 2627 } |
2623 | 2628 |
2624 *error_message = typer.error_message(); | 2629 *error_message = typer.error_message(); |
2625 return false; | 2630 return false; |
2626 } | 2631 } |
2627 | 2632 |
2628 } // namespace wasm | 2633 } // namespace wasm |
2629 } // namespace internal | 2634 } // namespace internal |
2630 } // namespace v8 | 2635 } // namespace v8 |
OLD | NEW |