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/typing-asm.h" | 5 #include "src/typing-asm.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "src/v8.h" | 9 #include "src/v8.h" |
| 10 | 10 |
| (...skipping 890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 901 // Only recurse at this point so that we avoid needing | 901 // Only recurse at this point so that we avoid needing |
| 902 // stdlib.Math to have a real type. | 902 // stdlib.Math to have a real type. |
| 903 RECURSE(VisitWithExpectation(expr->obj(), Type::Any(), "bad propety object")); | 903 RECURSE(VisitWithExpectation(expr->obj(), Type::Any(), "bad propety object")); |
| 904 | 904 |
| 905 // For heap view or function table access. | 905 // For heap view or function table access. |
| 906 if (computed_type_->IsArray()) { | 906 if (computed_type_->IsArray()) { |
| 907 VisitHeapAccess(expr, false, NULL); | 907 VisitHeapAccess(expr, false, NULL); |
| 908 return; | 908 return; |
| 909 } | 909 } |
| 910 | 910 |
| 911 // stdlib.x or foreign.x | |
| 912 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 911 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
| 913 if (proxy != NULL) { | 912 if (proxy != NULL) { |
| 914 Variable* var = proxy->var(); | 913 Variable* var = proxy->var(); |
| 915 if (var->location() == VariableLocation::PARAMETER && var->index() == 1) { | 914 if (var->location() == VariableLocation::PARAMETER && var->index() == 1) { |
| 916 // foreign.x is ok. | 915 // foreign.x - Function represent as () -> Any |
| 917 SetResult(expr, expected_type_); | 916 if (Type::Any()->Is(expected_type_)) { |
| 917 SetResult(expr, Type::Function(Type::Any(), zone())); | |
| 918 } else { | |
| 919 SetResult(expr, expected_type_); | |
| 920 } | |
| 918 return; | 921 return; |
| 919 } | 922 } |
| 920 } | 923 } |
| 921 | 924 |
| 922 FAIL(expr, "invalid property access"); | 925 FAIL(expr, "invalid property access"); |
| 923 } | 926 } |
| 924 | 927 |
| 925 | 928 |
| 926 void AsmTyper::VisitCall(Call* expr) { | 929 void AsmTyper::VisitCall(Call* expr) { |
| 927 Type* expected_type = expected_type_; | 930 Type* expected_type = expected_type_; |
| 928 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), | 931 RECURSE(VisitWithExpectation(expr->expression(), Type::Any(), |
| 929 "callee expected to be any")); | 932 "callee expected to be any")); |
| 930 StandardMember standard_member = kNone; | 933 StandardMember standard_member = kNone; |
| 931 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 934 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 932 if (proxy) { | 935 if (proxy) { |
| 933 standard_member = VariableAsStandardMember(proxy->var()); | 936 standard_member = VariableAsStandardMember(proxy->var()); |
| 934 } | 937 } |
| 935 if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) { | 938 if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) { |
| 936 FAIL(expr, "calls forbidden outside function bodies"); | 939 FAIL(expr, "calls forbidden outside function bodies"); |
| 937 } | 940 } |
| 938 if (proxy == NULL && !expr->expression()->IsProperty()) { | 941 if (proxy == NULL && !expr->expression()->IsProperty()) { |
| 939 FAIL(expr, "calls must be to bound variables or function tables"); | 942 FAIL(expr, "calls must be to bound variables or function tables"); |
| 940 } | 943 } |
| 941 if (computed_type_->IsFunction()) { | 944 if (computed_type_->IsFunction()) { |
| 942 FunctionType* fun_type = computed_type_->AsFunction(); | 945 FunctionType* fun_type = computed_type_->AsFunction(); |
| 943 Type* result_type = fun_type->Result(); | 946 Type* result_type = fun_type->Result(); |
| 944 ZoneList<Expression*>* args = expr->arguments(); | 947 ZoneList<Expression*>* args = expr->arguments(); |
| 945 if (fun_type->Arity() != args->length()) { | 948 if (Type::Any()->Is(result_type)) { |
| 946 FAIL(expr, "call with wrong arity"); | 949 // For foreign calls. |
| 947 } | 950 ZoneList<Expression*>* args = expr->arguments(); |
|
brucedawson
2016/02/05 23:35:50
Not a serious problem, but this line of code is re
bradn
2016/02/06 00:32:54
Ah, bad merge.
Thanks!
| |
| 948 for (int i = 0; i < args->length(); ++i) { | 951 for (int i = 0; i < args->length(); ++i) { |
| 949 Expression* arg = args->at(i); | 952 Expression* arg = args->at(i); |
| 950 RECURSE(VisitWithExpectation( | 953 RECURSE(VisitWithExpectation( |
| 951 arg, fun_type->Parameter(i), | 954 arg, Type::Any(), "foreign call argument expected to be any")); |
| 952 "call argument expected to match callee parameter")); | 955 // Checking for asm extern types explicitly, as the type system |
| 953 if (standard_member != kNone && standard_member != kMathFround && | 956 // doesn't correctly check their inheritance relationship. |
| 954 i == 0) { | 957 if (!computed_type_->Is(cache_.kAsmSigned) && |
| 955 result_type = computed_type_; | 958 !computed_type_->Is(cache_.kAsmFixnum) && |
| 956 } | 959 !computed_type_->Is(cache_.kAsmDouble)) { |
| 957 } | 960 FAIL(arg, |
| 958 // Handle polymorphic stdlib functions specially. | 961 "foreign call argument expected to be int, double, or fixnum"); |
| 959 if (standard_member == kMathCeil || standard_member == kMathFloor || | |
| 960 standard_member == kMathSqrt) { | |
| 961 if (!args->at(0)->bounds().upper->Is(cache_.kAsmFloat) && | |
| 962 !args->at(0)->bounds().upper->Is(cache_.kAsmDouble)) { | |
| 963 FAIL(expr, "illegal function argument type"); | |
| 964 } | |
| 965 } else if (standard_member == kMathAbs || standard_member == kMathMin || | |
| 966 standard_member == kMathMax) { | |
| 967 if (!args->at(0)->bounds().upper->Is(cache_.kAsmFloat) && | |
| 968 !args->at(0)->bounds().upper->Is(cache_.kAsmDouble) && | |
| 969 !args->at(0)->bounds().upper->Is(cache_.kAsmSigned)) { | |
| 970 FAIL(expr, "illegal function argument type"); | |
| 971 } | |
| 972 if (args->length() > 1) { | |
| 973 Type* other = Type::Intersect(args->at(0)->bounds().upper, | |
| 974 args->at(1)->bounds().upper, zone()); | |
| 975 if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) && | |
| 976 !other->Is(cache_.kAsmSigned)) { | |
| 977 FAIL(expr, "function arguments types don't match"); | |
| 978 } | 962 } |
| 979 } | 963 } |
| 964 intish_ = 0; | |
| 965 expr->expression()->set_bounds( | |
| 966 Bounds(Type::Function(Type::Any(), zone()))); | |
| 967 IntersectResult(expr, expected_type); | |
| 968 } else { | |
| 969 if (fun_type->Arity() != args->length()) { | |
| 970 FAIL(expr, "call with wrong arity"); | |
| 971 } | |
| 972 for (int i = 0; i < args->length(); ++i) { | |
| 973 Expression* arg = args->at(i); | |
| 974 RECURSE(VisitWithExpectation( | |
| 975 arg, fun_type->Parameter(i), | |
| 976 "call argument expected to match callee parameter")); | |
| 977 if (standard_member != kNone && standard_member != kMathFround && | |
| 978 i == 0) { | |
| 979 result_type = computed_type_; | |
| 980 } | |
| 981 } | |
| 982 // Handle polymorphic stdlib functions specially. | |
| 983 if (standard_member == kMathCeil || standard_member == kMathFloor || | |
| 984 standard_member == kMathSqrt) { | |
| 985 if (!args->at(0)->bounds().upper->Is(cache_.kAsmFloat) && | |
| 986 !args->at(0)->bounds().upper->Is(cache_.kAsmDouble)) { | |
| 987 FAIL(expr, "illegal function argument type"); | |
| 988 } | |
| 989 } else if (standard_member == kMathAbs || standard_member == kMathMin || | |
| 990 standard_member == kMathMax) { | |
| 991 if (!args->at(0)->bounds().upper->Is(cache_.kAsmFloat) && | |
| 992 !args->at(0)->bounds().upper->Is(cache_.kAsmDouble) && | |
| 993 !args->at(0)->bounds().upper->Is(cache_.kAsmSigned)) { | |
| 994 FAIL(expr, "illegal function argument type"); | |
| 995 } | |
| 996 if (args->length() > 1) { | |
| 997 Type* other = Type::Intersect(args->at(0)->bounds().upper, | |
| 998 args->at(1)->bounds().upper, zone()); | |
| 999 if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) && | |
| 1000 !other->Is(cache_.kAsmSigned)) { | |
| 1001 FAIL(expr, "function arguments types don't match"); | |
| 1002 } | |
| 1003 } | |
| 1004 } | |
| 1005 intish_ = 0; | |
| 1006 IntersectResult(expr, result_type); | |
| 980 } | 1007 } |
| 981 intish_ = 0; | |
| 982 IntersectResult(expr, result_type); | |
| 983 } else if (computed_type_->Is(Type::Any())) { | |
| 984 // For foreign calls. | |
| 985 ZoneList<Expression*>* args = expr->arguments(); | |
| 986 for (int i = 0; i < args->length(); ++i) { | |
| 987 Expression* arg = args->at(i); | |
| 988 RECURSE(VisitWithExpectation(arg, Type::Any(), | |
| 989 "foreign call argument expected to be any")); | |
| 990 // Checking for asm extern types explicitly, as the type system | |
| 991 // doesn't correctly check their inheritance relationship. | |
| 992 if (!computed_type_->Is(cache_.kAsmSigned) && | |
| 993 !computed_type_->Is(cache_.kAsmFixnum) && | |
| 994 !computed_type_->Is(cache_.kAsmDouble)) { | |
| 995 FAIL(arg, | |
| 996 "foreign call argument expected to be int, double, or fixnum"); | |
| 997 } | |
| 998 } | |
| 999 intish_ = kMaxUncombinedAdditiveSteps; | |
| 1000 expr->expression()->set_bounds(Bounds(Type::Function())); | |
| 1001 IntersectResult(expr, expected_type); | |
| 1002 } else { | 1008 } else { |
| 1003 FAIL(expr, "invalid callee"); | 1009 FAIL(expr, "invalid callee"); |
| 1004 } | 1010 } |
| 1005 } | 1011 } |
| 1006 | 1012 |
| 1007 | 1013 |
| 1008 void AsmTyper::VisitCallNew(CallNew* expr) { | 1014 void AsmTyper::VisitCallNew(CallNew* expr) { |
| 1009 if (in_function_) { | 1015 if (in_function_) { |
| 1010 FAIL(expr, "new not allowed in module function"); | 1016 FAIL(expr, "new not allowed in module function"); |
| 1011 } | 1017 } |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1529 | 1535 |
| 1530 | 1536 |
| 1531 void AsmTyper::VisitRewritableAssignmentExpression( | 1537 void AsmTyper::VisitRewritableAssignmentExpression( |
| 1532 RewritableAssignmentExpression* expr) { | 1538 RewritableAssignmentExpression* expr) { |
| 1533 RECURSE(Visit(expr->expression())); | 1539 RECURSE(Visit(expr->expression())); |
| 1534 } | 1540 } |
| 1535 | 1541 |
| 1536 | 1542 |
| 1537 } // namespace internal | 1543 } // namespace internal |
| 1538 } // namespace v8 | 1544 } // namespace v8 |
| OLD | NEW |