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 #include "src/typing-asm.h" | 7 #include "src/typing-asm.h" |
8 | 8 |
9 #include "src/ast/ast.h" | 9 #include "src/ast/ast.h" |
10 #include "src/ast/scopes.h" | 10 #include "src/ast/scopes.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 DCHECK(!HasStackOverflow()); \ | 31 DCHECK(!HasStackOverflow()); \ |
32 call; \ | 32 call; \ |
33 if (HasStackOverflow()) return; \ | 33 if (HasStackOverflow()) return; \ |
34 if (!valid_) return; \ | 34 if (!valid_) return; \ |
35 } while (false) | 35 } while (false) |
36 | 36 |
37 | 37 |
38 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, | 38 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, |
39 FunctionLiteral* root) | 39 FunctionLiteral* root) |
40 : zone_(zone), | 40 : zone_(zone), |
| 41 isolate_(isolate), |
41 script_(script), | 42 script_(script), |
42 root_(root), | 43 root_(root), |
43 valid_(true), | 44 valid_(true), |
| 45 allow_simd_(false), |
44 intish_(0), | 46 intish_(0), |
45 stdlib_types_(zone), | 47 stdlib_types_(zone), |
46 stdlib_heap_types_(zone), | 48 stdlib_heap_types_(zone), |
47 stdlib_math_types_(zone), | 49 stdlib_math_types_(zone), |
48 global_variable_type_(HashMap::PointersMatch, | 50 #define V(NAME, Name, name, lane_count, lane_type) \ |
49 ZoneHashMap::kDefaultHashMapCapacity, | 51 stdlib_simd_##name##_types_(zone), |
50 ZoneAllocationPolicy(zone)), | 52 SIMD128_TYPES(V) |
| 53 #undef V |
| 54 global_variable_type_(HashMap::PointersMatch, |
| 55 ZoneHashMap::kDefaultHashMapCapacity, |
| 56 ZoneAllocationPolicy(zone)), |
51 local_variable_type_(HashMap::PointersMatch, | 57 local_variable_type_(HashMap::PointersMatch, |
52 ZoneHashMap::kDefaultHashMapCapacity, | 58 ZoneHashMap::kDefaultHashMapCapacity, |
53 ZoneAllocationPolicy(zone)), | 59 ZoneAllocationPolicy(zone)), |
54 in_function_(false), | 60 in_function_(false), |
55 building_function_tables_(false), | 61 building_function_tables_(false), |
56 cache_(TypeCache::Get()) { | 62 cache_(TypeCache::Get()) { |
57 InitializeAstVisitor(isolate); | 63 InitializeAstVisitor(isolate); |
58 InitializeStdlib(); | 64 InitializeStdlib(); |
59 } | 65 } |
60 | 66 |
(...skipping 25 matching lines...) Expand all Loading... |
86 // Validate global variables. | 92 // Validate global variables. |
87 RECURSE(VisitStatements(fun->body())); | 93 RECURSE(VisitStatements(fun->body())); |
88 | 94 |
89 // Validate function annotations. | 95 // Validate function annotations. |
90 for (int i = 0; i < decls->length(); ++i) { | 96 for (int i = 0; i < decls->length(); ++i) { |
91 FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration(); | 97 FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration(); |
92 if (decl != NULL) { | 98 if (decl != NULL) { |
93 RECURSE(VisitFunctionAnnotation(decl->fun())); | 99 RECURSE(VisitFunctionAnnotation(decl->fun())); |
94 Variable* var = decl->proxy()->var(); | 100 Variable* var = decl->proxy()->var(); |
95 DCHECK(GetType(var) == NULL); | 101 DCHECK(GetType(var) == NULL); |
| 102 if (property_info_ != NULL) { |
| 103 SetVariableInfo(var, property_info_); |
| 104 property_info_ = NULL; |
| 105 } |
96 SetType(var, computed_type_); | 106 SetType(var, computed_type_); |
97 DCHECK(GetType(var) != NULL); | 107 DCHECK(GetType(var) != NULL); |
98 } | 108 } |
99 } | 109 } |
100 | 110 |
101 // Build function tables. | 111 // Build function tables. |
102 building_function_tables_ = true; | 112 building_function_tables_ = true; |
103 RECURSE(VisitStatements(fun->body())); | 113 RECURSE(VisitStatements(fun->body())); |
104 building_function_tables_ = false; | 114 building_function_tables_ = false; |
105 | 115 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 ExpressionStatement* stmt = body->at(i)->AsExpressionStatement(); | 184 ExpressionStatement* stmt = body->at(i)->AsExpressionStatement(); |
175 if (stmt == NULL) break; | 185 if (stmt == NULL) break; |
176 Assignment* expr = stmt->expression()->AsAssignment(); | 186 Assignment* expr = stmt->expression()->AsAssignment(); |
177 if (expr == NULL || expr->is_compound()) break; | 187 if (expr == NULL || expr->is_compound()) break; |
178 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 188 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
179 if (proxy == NULL) break; | 189 if (proxy == NULL) break; |
180 Variable* var = proxy->var(); | 190 Variable* var = proxy->var(); |
181 if (var->location() != VariableLocation::PARAMETER || var->index() != i) | 191 if (var->location() != VariableLocation::PARAMETER || var->index() != i) |
182 break; | 192 break; |
183 RECURSE(VisitExpressionAnnotation(expr->value(), var, false)); | 193 RECURSE(VisitExpressionAnnotation(expr->value(), var, false)); |
| 194 if (property_info_ != NULL) { |
| 195 SetVariableInfo(var, property_info_); |
| 196 property_info_ = NULL; |
| 197 } |
184 SetType(var, computed_type_); | 198 SetType(var, computed_type_); |
185 type->InitParameter(i, computed_type_); | 199 type->InitParameter(i, computed_type_); |
186 good = true; | 200 good = true; |
187 } | 201 } |
188 if (!good) FAIL(fun, "missing parameter type annotations"); | 202 if (!good) FAIL(fun, "missing parameter type annotations"); |
189 | 203 |
190 SetResult(fun, type); | 204 SetResult(fun, type); |
191 } | 205 } |
192 | 206 |
193 | 207 |
194 void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var, | 208 void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var, |
195 bool is_return) { | 209 bool is_return) { |
196 // Normal +x or x|0 annotations. | 210 // Normal +x or x|0 annotations. |
197 BinaryOperation* bin = expr->AsBinaryOperation(); | 211 BinaryOperation* bin = expr->AsBinaryOperation(); |
198 if (bin != NULL) { | 212 if (bin != NULL) { |
199 if (var != NULL) { | 213 if (var != NULL) { |
200 VariableProxy* left = bin->left()->AsVariableProxy(); | 214 VariableProxy* proxy = bin->left()->AsVariableProxy(); |
201 if (!left) { | 215 if (proxy == NULL) { |
202 FAIL(expr, "variable name expected in type annotation"); | 216 FAIL(bin->left(), "expected variable for type annotation"); |
203 } | 217 } |
204 if (left->var() != var) { | 218 if (proxy->var() != var) { |
205 FAIL(left, "variable type annotation references other variable"); | 219 FAIL(proxy, "annotation source doesn't match destination"); |
206 } | 220 } |
207 } | 221 } |
208 Literal* right = bin->right()->AsLiteral(); | 222 Literal* right = bin->right()->AsLiteral(); |
209 if (right != NULL) { | 223 if (right != NULL) { |
210 switch (bin->op()) { | 224 switch (bin->op()) { |
211 case Token::MUL: // We encode +x as x*1.0 | 225 case Token::MUL: // We encode +x as x*1.0 |
212 if (right->raw_value()->ContainsDot() && | 226 if (right->raw_value()->ContainsDot() && |
213 right->raw_value()->AsNumber() == 1.0) { | 227 right->raw_value()->AsNumber() == 1.0) { |
214 SetResult(expr, cache_.kAsmDouble); | 228 SetResult(expr, cache_.kAsmDouble); |
215 return; | 229 return; |
(...skipping 18 matching lines...) Expand all Loading... |
234 } | 248 } |
235 | 249 |
236 // Numbers or the undefined literal (for empty returns). | 250 // Numbers or the undefined literal (for empty returns). |
237 if (expr->IsLiteral()) { | 251 if (expr->IsLiteral()) { |
238 RECURSE(VisitWithExpectation(expr, Type::Any(), "invalid literal")); | 252 RECURSE(VisitWithExpectation(expr, Type::Any(), "invalid literal")); |
239 return; | 253 return; |
240 } | 254 } |
241 | 255 |
242 Call* call = expr->AsCall(); | 256 Call* call = expr->AsCall(); |
243 if (call != NULL) { | 257 if (call != NULL) { |
244 if (call->expression()->IsVariableProxy()) { | 258 VariableProxy* proxy = call->expression()->AsVariableProxy(); |
245 RECURSE(VisitWithExpectation( | 259 if (proxy != NULL) { |
246 call->expression(), Type::Any(zone()), | 260 VariableInfo* info = GetVariableInfo(proxy->var(), false); |
247 "only fround allowed on expression annotations")); | 261 if (!info || |
248 if (!computed_type_->Is( | 262 (!info->is_check_function && !info->is_constructor_function)) { |
249 Type::Function(cache_.kAsmFloat, Type::Number(zone()), zone()))) { | 263 if (allow_simd_) { |
250 FAIL(call->expression(), | 264 FAIL(call->expression(), |
251 "only fround allowed on expression annotations"); | 265 "only fround/SIMD.checks allowed on expression annotations"); |
| 266 } else { |
| 267 FAIL(call->expression(), |
| 268 "only fround allowed on expression annotations"); |
| 269 } |
252 } | 270 } |
253 if (call->arguments()->length() != 1) { | 271 Type* type = info->type; |
254 FAIL(call, "invalid argument count calling fround"); | 272 DCHECK(type->IsFunction()); |
| 273 if (info->is_check_function) { |
| 274 DCHECK(type->AsFunction()->Arity() == 1); |
255 } | 275 } |
256 SetResult(expr, cache_.kAsmFloat); | 276 if (call->arguments()->length() != type->AsFunction()->Arity()) { |
| 277 FAIL(call, "invalid argument count calling function"); |
| 278 } |
| 279 SetResult(expr, type->AsFunction()->Result()); |
257 return; | 280 return; |
258 } | 281 } |
259 } | 282 } |
260 | 283 |
261 FAIL(expr, "invalid type annotation"); | 284 FAIL(expr, "invalid type annotation"); |
262 } | 285 } |
263 | 286 |
264 | 287 |
265 void AsmTyper::VisitStatements(ZoneList<Statement*>* stmts) { | 288 void AsmTyper::VisitStatements(ZoneList<Statement*>* stmts) { |
266 for (int i = 0; i < stmts->length(); ++i) { | 289 for (int i = 0; i < stmts->length(); ++i) { |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 if (!then_type->Is(else_type) || !else_type->Is(then_type)) { | 515 if (!then_type->Is(else_type) || !else_type->Is(then_type)) { |
493 FAIL(expr, "then and else expressions in ? must have the same type"); | 516 FAIL(expr, "then and else expressions in ? must have the same type"); |
494 } | 517 } |
495 | 518 |
496 IntersectResult(expr, then_type); | 519 IntersectResult(expr, then_type); |
497 } | 520 } |
498 | 521 |
499 | 522 |
500 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { | 523 void AsmTyper::VisitVariableProxy(VariableProxy* expr) { |
501 Variable* var = expr->var(); | 524 Variable* var = expr->var(); |
502 if (GetType(var) == NULL) { | 525 VariableInfo* info = GetVariableInfo(var, false); |
| 526 if (info == NULL || info->type == NULL) { |
503 FAIL(expr, "unbound variable"); | 527 FAIL(expr, "unbound variable"); |
504 } | 528 } |
505 Type* type = Type::Intersect(GetType(var), expected_type_, zone()); | 529 if (property_info_ != NULL) { |
| 530 SetVariableInfo(var, property_info_); |
| 531 property_info_ = NULL; |
| 532 } |
| 533 Type* type = Type::Intersect(info->type, expected_type_, zone()); |
506 if (type->Is(cache_.kAsmInt)) { | 534 if (type->Is(cache_.kAsmInt)) { |
507 type = cache_.kAsmInt; | 535 type = cache_.kAsmInt; |
508 } | 536 } |
509 SetType(var, type); | 537 SetType(var, type); |
510 intish_ = 0; | 538 intish_ = 0; |
511 IntersectResult(expr, type); | 539 IntersectResult(expr, type); |
512 } | 540 } |
513 | 541 |
514 | 542 |
515 void AsmTyper::VisitLiteral(Literal* expr, bool is_return) { | 543 void AsmTyper::VisitLiteral(Literal* expr, bool is_return) { |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 FAIL(expr, "illegal type in assignment"); | 760 FAIL(expr, "illegal type in assignment"); |
733 } | 761 } |
734 } else { | 762 } else { |
735 IntersectResult(expr, expected_type_); | 763 IntersectResult(expr, expected_type_); |
736 IntersectResult(expr, result_type); | 764 IntersectResult(expr, result_type); |
737 } | 765 } |
738 } | 766 } |
739 } | 767 } |
740 | 768 |
741 | 769 |
| 770 bool AsmTyper::IsStdlibObject(Expression* expr) { |
| 771 VariableProxy* proxy = expr->AsVariableProxy(); |
| 772 if (proxy == NULL) { |
| 773 return false; |
| 774 } |
| 775 Variable* var = proxy->var(); |
| 776 VariableInfo* info = GetVariableInfo(var, false); |
| 777 if (info) { |
| 778 if (info->is_stdlib_object) return info->is_stdlib_object; |
| 779 } |
| 780 if (var->location() != VariableLocation::PARAMETER || var->index() != 0) { |
| 781 return false; |
| 782 } |
| 783 info = GetVariableInfo(var, true); |
| 784 info->type = Type::Object(); |
| 785 info->is_stdlib_object = true; |
| 786 return true; |
| 787 } |
| 788 |
| 789 |
| 790 Expression* AsmTyper::GetReceiverOfPropertyAccess(Expression* expr, |
| 791 const char* name) { |
| 792 Property* property = expr->AsProperty(); |
| 793 if (property == NULL) { |
| 794 return NULL; |
| 795 } |
| 796 Literal* key = property->key()->AsLiteral(); |
| 797 if (key == NULL || !key->IsPropertyName() || |
| 798 !key->AsPropertyName()->IsUtf8EqualTo(CStrVector(name))) { |
| 799 return NULL; |
| 800 } |
| 801 return property->obj(); |
| 802 } |
| 803 |
| 804 |
| 805 bool AsmTyper::IsMathObject(Expression* expr) { |
| 806 Expression* obj = GetReceiverOfPropertyAccess(expr, "Math"); |
| 807 return obj && IsStdlibObject(obj); |
| 808 } |
| 809 |
| 810 |
| 811 bool AsmTyper::IsSIMDObject(Expression* expr) { |
| 812 Expression* obj = GetReceiverOfPropertyAccess(expr, "SIMD"); |
| 813 return obj && IsStdlibObject(obj); |
| 814 } |
| 815 |
| 816 |
| 817 bool AsmTyper::IsSIMDTypeObject(Expression* expr, const char* name) { |
| 818 Expression* obj = GetReceiverOfPropertyAccess(expr, name); |
| 819 return obj && IsSIMDObject(obj); |
| 820 } |
| 821 |
| 822 |
742 void AsmTyper::VisitProperty(Property* expr) { | 823 void AsmTyper::VisitProperty(Property* expr) { |
743 // stdlib.Math.x | 824 if (IsMathObject(expr->obj())) { |
744 Property* inner_prop = expr->obj()->AsProperty(); | 825 VisitLibraryAccess(&stdlib_math_types_, expr); |
745 if (inner_prop != NULL) { | 826 return; |
746 // Get property name. | 827 } |
747 Literal* key = expr->key()->AsLiteral(); | 828 #define V(NAME, Name, name, lane_count, lane_type) \ |
748 if (key == NULL || !key->IsPropertyName()) | 829 if (IsSIMDTypeObject(expr->obj(), #Name)) { \ |
749 FAIL(expr, "invalid type annotation on property 2"); | 830 VisitLibraryAccess(&stdlib_simd_##name##_types_, expr); \ |
750 Handle<String> name = key->AsPropertyName(); | 831 return; \ |
751 | 832 } \ |
752 // Check that inner property name is "Math". | 833 if (IsSIMDTypeObject(expr, #Name)) { \ |
753 Literal* math_key = inner_prop->key()->AsLiteral(); | 834 VariableInfo* info = stdlib_simd_##name##_constructor_type_; \ |
754 if (math_key == NULL || !math_key->IsPropertyName() || | 835 SetResult(expr, info->type); \ |
755 !math_key->AsPropertyName()->IsUtf8EqualTo(CStrVector("Math"))) | 836 property_info_ = info; \ |
756 FAIL(expr, "invalid type annotation on stdlib (a1)"); | 837 return; \ |
757 | 838 } |
758 // Check that object is stdlib. | 839 SIMD128_TYPES(V) |
759 VariableProxy* proxy = inner_prop->obj()->AsVariableProxy(); | 840 #undef V |
760 if (proxy == NULL) FAIL(expr, "invalid type annotation on stdlib (a2)"); | 841 if (IsStdlibObject(expr->obj())) { |
761 Variable* var = proxy->var(); | 842 VisitLibraryAccess(&stdlib_types_, expr); |
762 if (var->location() != VariableLocation::PARAMETER || var->index() != 0) | |
763 FAIL(expr, "invalid type annotation on stdlib (a3)"); | |
764 | |
765 // Look up library type. | |
766 Type* type = LibType(stdlib_math_types_, name); | |
767 if (type == NULL) FAIL(expr, "unknown standard function 3 "); | |
768 SetResult(expr, type); | |
769 return; | 843 return; |
770 } | 844 } |
771 | 845 |
| 846 property_info_ = NULL; |
| 847 |
772 // Only recurse at this point so that we avoid needing | 848 // Only recurse at this point so that we avoid needing |
773 // stdlib.Math to have a real type. | 849 // stdlib.Math to have a real type. |
774 RECURSE(VisitWithExpectation(expr->obj(), Type::Any(), "bad propety object")); | 850 RECURSE(VisitWithExpectation(expr->obj(), Type::Any(), "bad propety object")); |
775 | 851 |
776 // For heap view or function table access. | 852 // For heap view or function table access. |
777 if (computed_type_->IsArray()) { | 853 if (computed_type_->IsArray()) { |
778 VisitHeapAccess(expr, false, NULL); | 854 VisitHeapAccess(expr, false, NULL); |
779 return; | 855 return; |
780 } | 856 } |
781 | 857 |
782 // Get property name. | |
783 Literal* key = expr->key()->AsLiteral(); | |
784 if (key == NULL || !key->IsPropertyName()) | |
785 FAIL(expr, "invalid type annotation on property 3"); | |
786 Handle<String> name = key->AsPropertyName(); | |
787 | |
788 // stdlib.x or foreign.x | 858 // stdlib.x or foreign.x |
789 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 859 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
790 if (proxy != NULL) { | 860 if (proxy != NULL) { |
791 Variable* var = proxy->var(); | 861 Variable* var = proxy->var(); |
792 if (var->location() != VariableLocation::PARAMETER) { | 862 if (var->location() == VariableLocation::PARAMETER && var->index() == 1) { |
793 FAIL(expr, "invalid type annotation on variable"); | 863 // foreign.x is ok. |
794 } | 864 SetResult(expr, expected_type_); |
795 switch (var->index()) { | 865 return; |
796 case 0: { | |
797 // Object is stdlib, look up library type. | |
798 Type* type = LibType(stdlib_types_, name); | |
799 if (type == NULL) { | |
800 FAIL(expr, "unknown standard function 4"); | |
801 } | |
802 SetResult(expr, type); | |
803 return; | |
804 } | |
805 case 1: | |
806 // Object is foreign lib. | |
807 SetResult(expr, expected_type_); | |
808 return; | |
809 default: | |
810 FAIL(expr, "invalid type annotation on parameter"); | |
811 } | 866 } |
812 } | 867 } |
813 | 868 |
814 FAIL(expr, "invalid property access"); | 869 FAIL(expr, "invalid property access"); |
815 } | 870 } |
816 | 871 |
817 | 872 |
818 void AsmTyper::VisitCall(Call* expr) { | 873 void AsmTyper::VisitCall(Call* expr) { |
819 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), | 874 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), |
820 "callee expected to be any")); | 875 "callee expected to be any")); |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1136 void AsmTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) { | 1191 void AsmTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) { |
1137 FAIL(expr, "super property reference not allowed"); | 1192 FAIL(expr, "super property reference not allowed"); |
1138 } | 1193 } |
1139 | 1194 |
1140 | 1195 |
1141 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { | 1196 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) { |
1142 FAIL(expr, "call reference not allowed"); | 1197 FAIL(expr, "call reference not allowed"); |
1143 } | 1198 } |
1144 | 1199 |
1145 | 1200 |
| 1201 void AsmTyper::InitializeStdlibSIMD() { |
| 1202 #define V(NAME, Name, name, lane_count, lane_type) \ |
| 1203 { \ |
| 1204 Type* type = Type::Function(Type::Name(isolate_, zone()), Type::Any(), \ |
| 1205 lane_count, zone()); \ |
| 1206 for (int i = 0; i < lane_count; ++i) { \ |
| 1207 type->AsFunction()->InitParameter(i, Type::Number()); \ |
| 1208 } \ |
| 1209 stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \ |
| 1210 stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \ |
| 1211 } |
| 1212 SIMD128_TYPES(V) |
| 1213 #undef V |
| 1214 } |
| 1215 |
| 1216 |
1146 void AsmTyper::InitializeStdlib() { | 1217 void AsmTyper::InitializeStdlib() { |
| 1218 if (allow_simd_) { |
| 1219 InitializeStdlibSIMD(); |
| 1220 } |
1147 Type* number_type = Type::Number(zone()); | 1221 Type* number_type = Type::Number(zone()); |
1148 Type* double_type = cache_.kAsmDouble; | 1222 Type* double_type = cache_.kAsmDouble; |
1149 Type* double_fn1_type = Type::Function(double_type, double_type, zone()); | 1223 Type* double_fn1_type = Type::Function(double_type, double_type, zone()); |
1150 Type* double_fn2_type = | 1224 Type* double_fn2_type = |
1151 Type::Function(double_type, double_type, double_type, zone()); | 1225 Type::Function(double_type, double_type, double_type, zone()); |
1152 | 1226 |
1153 Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone()); | 1227 Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone()); |
1154 Type* imul_type = | 1228 Type* imul_type = |
1155 Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone()); | 1229 Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone()); |
1156 // TODO(bradnelson): currently only approximating the proper intersection type | 1230 // TODO(bradnelson): currently only approximating the proper intersection type |
(...skipping 13 matching lines...) Expand all Loading... |
1170 {"imul", imul_type}, {"abs", abs_type}, | 1244 {"imul", imul_type}, {"abs", abs_type}, |
1171 {"ceil", double_fn1_type}, {"floor", double_fn1_type}, | 1245 {"ceil", double_fn1_type}, {"floor", double_fn1_type}, |
1172 {"fround", fround_type}, {"pow", double_fn2_type}, | 1246 {"fround", fround_type}, {"pow", double_fn2_type}, |
1173 {"exp", double_fn1_type}, {"log", double_fn1_type}, | 1247 {"exp", double_fn1_type}, {"log", double_fn1_type}, |
1174 {"min", double_fn2_type}, {"max", double_fn2_type}, | 1248 {"min", double_fn2_type}, {"max", double_fn2_type}, |
1175 {"sqrt", double_fn1_type}, {"cos", double_fn1_type}, | 1249 {"sqrt", double_fn1_type}, {"cos", double_fn1_type}, |
1176 {"sin", double_fn1_type}, {"tan", double_fn1_type}, | 1250 {"sin", double_fn1_type}, {"tan", double_fn1_type}, |
1177 {"acos", double_fn1_type}, {"asin", double_fn1_type}, | 1251 {"acos", double_fn1_type}, {"asin", double_fn1_type}, |
1178 {"atan", double_fn1_type}, {"atan2", double_fn2_type}}; | 1252 {"atan", double_fn1_type}, {"atan2", double_fn2_type}}; |
1179 for (unsigned i = 0; i < arraysize(math); ++i) { | 1253 for (unsigned i = 0; i < arraysize(math); ++i) { |
1180 stdlib_math_types_[math[i].name] = math[i].type; | 1254 stdlib_math_types_[math[i].name] = new (zone()) VariableInfo(math[i].type); |
1181 } | 1255 } |
| 1256 stdlib_math_types_["fround"]->is_check_function = true; |
1182 | 1257 |
1183 stdlib_types_["Infinity"] = double_type; | 1258 stdlib_types_["Infinity"] = new (zone()) VariableInfo(double_type); |
1184 stdlib_types_["NaN"] = double_type; | 1259 stdlib_types_["NaN"] = new (zone()) VariableInfo(double_type); |
1185 Type* buffer_type = Type::Any(zone()); | 1260 Type* buffer_type = Type::Any(zone()); |
1186 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ | 1261 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ |
1187 stdlib_types_[#TypeName "Array"] = \ | 1262 stdlib_types_[#TypeName "Array"] = new (zone()) VariableInfo( \ |
1188 Type::Function(cache_.k##TypeName##Array, buffer_type, zone()); | 1263 Type::Function(cache_.k##TypeName##Array, buffer_type, zone())); |
1189 TYPED_ARRAYS(TYPED_ARRAY) | 1264 TYPED_ARRAYS(TYPED_ARRAY) |
1190 #undef TYPED_ARRAY | 1265 #undef TYPED_ARRAY |
1191 | 1266 |
1192 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ | 1267 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \ |
1193 stdlib_heap_types_[#TypeName "Array"] = \ | 1268 stdlib_heap_types_[#TypeName "Array"] = new (zone()) VariableInfo( \ |
1194 Type::Function(cache_.k##TypeName##Array, buffer_type, zone()); | 1269 Type::Function(cache_.k##TypeName##Array, buffer_type, zone())); |
1195 TYPED_ARRAYS(TYPED_ARRAY) | 1270 TYPED_ARRAYS(TYPED_ARRAY) |
1196 #undef TYPED_ARRAY | 1271 #undef TYPED_ARRAY |
1197 } | 1272 } |
1198 | 1273 |
1199 | 1274 |
1200 Type* AsmTyper::LibType(ObjectTypeMap map, Handle<String> name) { | 1275 void AsmTyper::VisitLibraryAccess(ObjectTypeMap* map, Property* expr) { |
| 1276 Literal* key = expr->key()->AsLiteral(); |
| 1277 if (key == NULL || !key->IsPropertyName()) |
| 1278 FAIL(expr, "invalid key used on stdlib member"); |
| 1279 Handle<String> name = key->AsPropertyName(); |
| 1280 VariableInfo* info = LibType(map, name); |
| 1281 if (info == NULL || info->type == NULL) FAIL(expr, "unknown stdlib function"); |
| 1282 SetResult(expr, info->type); |
| 1283 property_info_ = info; |
| 1284 } |
| 1285 |
| 1286 |
| 1287 AsmTyper::VariableInfo* AsmTyper::LibType(ObjectTypeMap* map, |
| 1288 Handle<String> name) { |
1201 base::SmartArrayPointer<char> aname = name->ToCString(); | 1289 base::SmartArrayPointer<char> aname = name->ToCString(); |
1202 ObjectTypeMap::iterator i = map.find(std::string(aname.get())); | 1290 ObjectTypeMap::iterator i = map->find(std::string(aname.get())); |
1203 if (i == map.end()) { | 1291 if (i == map->end()) { |
1204 return NULL; | 1292 return NULL; |
1205 } | 1293 } |
1206 return i->second; | 1294 return i->second; |
1207 } | 1295 } |
1208 | 1296 |
1209 | 1297 |
1210 void AsmTyper::SetType(Variable* variable, Type* type) { | 1298 void AsmTyper::SetType(Variable* variable, Type* type) { |
1211 ZoneHashMap::Entry* entry; | 1299 VariableInfo* info = GetVariableInfo(variable, true); |
1212 if (in_function_) { | 1300 info->type = type; |
1213 entry = local_variable_type_.LookupOrInsert( | |
1214 variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone())); | |
1215 } else { | |
1216 entry = global_variable_type_.LookupOrInsert( | |
1217 variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone())); | |
1218 } | |
1219 entry->value = reinterpret_cast<void*>(type); | |
1220 } | 1301 } |
1221 | 1302 |
1222 | 1303 |
1223 Type* AsmTyper::GetType(Variable* variable) { | 1304 Type* AsmTyper::GetType(Variable* variable) { |
1224 i::ZoneHashMap::Entry* entry = NULL; | 1305 VariableInfo* info = GetVariableInfo(variable, false); |
1225 if (in_function_) { | 1306 if (!info) return NULL; |
1226 entry = local_variable_type_.Lookup(variable, ComputePointerHash(variable)); | 1307 return info->type; |
1227 } | |
1228 if (entry == NULL) { | |
1229 entry = | |
1230 global_variable_type_.Lookup(variable, ComputePointerHash(variable)); | |
1231 } | |
1232 if (entry == NULL) { | |
1233 return NULL; | |
1234 } else { | |
1235 return reinterpret_cast<Type*>(entry->value); | |
1236 } | |
1237 } | 1308 } |
1238 | 1309 |
1239 | 1310 |
| 1311 AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable, |
| 1312 bool setting) { |
| 1313 ZoneHashMap::Entry* entry; |
| 1314 ZoneHashMap* map; |
| 1315 if (in_function_) { |
| 1316 map = &local_variable_type_; |
| 1317 } else { |
| 1318 map = &global_variable_type_; |
| 1319 } |
| 1320 if (setting) { |
| 1321 entry = map->LookupOrInsert(variable, ComputePointerHash(variable), |
| 1322 ZoneAllocationPolicy(zone())); |
| 1323 } else { |
| 1324 entry = map->Lookup(variable, ComputePointerHash(variable)); |
| 1325 if (!entry && in_function_) { |
| 1326 entry = |
| 1327 global_variable_type_.Lookup(variable, ComputePointerHash(variable)); |
| 1328 } |
| 1329 } |
| 1330 if (!entry) return NULL; |
| 1331 if (!entry->value) { |
| 1332 if (!setting) return NULL; |
| 1333 entry->value = new (zone()) VariableInfo; |
| 1334 } |
| 1335 return reinterpret_cast<VariableInfo*>(entry->value); |
| 1336 } |
| 1337 |
| 1338 |
| 1339 void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) { |
| 1340 VariableInfo* dest = GetVariableInfo(variable, true); |
| 1341 dest->type = info->type; |
| 1342 dest->is_stdlib_object = info->is_stdlib_object; |
| 1343 dest->is_check_function = info->is_check_function; |
| 1344 dest->is_constructor_function = info->is_constructor_function; |
| 1345 } |
| 1346 |
| 1347 |
1240 void AsmTyper::SetResult(Expression* expr, Type* type) { | 1348 void AsmTyper::SetResult(Expression* expr, Type* type) { |
1241 computed_type_ = type; | 1349 computed_type_ = type; |
1242 expr->set_bounds(Bounds(computed_type_)); | 1350 expr->set_bounds(Bounds(computed_type_)); |
1243 } | 1351 } |
1244 | 1352 |
1245 | 1353 |
1246 void AsmTyper::IntersectResult(Expression* expr, Type* type) { | 1354 void AsmTyper::IntersectResult(Expression* expr, Type* type) { |
1247 computed_type_ = type; | 1355 computed_type_ = type; |
1248 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); | 1356 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); |
1249 expr->set_bounds(Bounds(bounded_type)); | 1357 expr->set_bounds(Bounds(bounded_type)); |
(...skipping 12 matching lines...) Expand all Loading... |
1262 computed_type_->Print(); | 1370 computed_type_->Print(); |
1263 PrintF("Expected type: "); | 1371 PrintF("Expected type: "); |
1264 expected_type_->Print(); | 1372 expected_type_->Print(); |
1265 #endif | 1373 #endif |
1266 FAIL(expr, msg); | 1374 FAIL(expr, msg); |
1267 } | 1375 } |
1268 expected_type_ = save; | 1376 expected_type_ = save; |
1269 } | 1377 } |
1270 } // namespace internal | 1378 } // namespace internal |
1271 } // namespace v8 | 1379 } // namespace v8 |
OLD | NEW |