| 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 #undef V | 55 #undef V |
| 56 global_variable_type_(HashMap::PointersMatch, | 56 global_variable_type_(HashMap::PointersMatch, |
| 57 ZoneHashMap::kDefaultHashMapCapacity, | 57 ZoneHashMap::kDefaultHashMapCapacity, |
| 58 ZoneAllocationPolicy(zone)), | 58 ZoneAllocationPolicy(zone)), |
| 59 local_variable_type_(HashMap::PointersMatch, | 59 local_variable_type_(HashMap::PointersMatch, |
| 60 ZoneHashMap::kDefaultHashMapCapacity, | 60 ZoneHashMap::kDefaultHashMapCapacity, |
| 61 ZoneAllocationPolicy(zone)), | 61 ZoneAllocationPolicy(zone)), |
| 62 in_function_(false), | 62 in_function_(false), |
| 63 building_function_tables_(false), | 63 building_function_tables_(false), |
| 64 visiting_exports_(false), | 64 visiting_exports_(false), |
| 65 cache_(TypeCache::Get()) { | 65 cache_(TypeCache::Get()), |
| 66 bounds_(zone) { |
| 66 InitializeAstVisitor(isolate); | 67 InitializeAstVisitor(isolate); |
| 67 InitializeStdlib(); | 68 InitializeStdlib(); |
| 68 } | 69 } |
| 69 | 70 |
| 70 | 71 |
| 71 bool AsmTyper::Validate() { | 72 bool AsmTyper::Validate() { |
| 72 VisitAsmModule(root_); | 73 VisitAsmModule(root_); |
| 73 return valid_ && !HasStackOverflow(); | 74 return valid_ && !HasStackOverflow(); |
| 74 } | 75 } |
| 75 | 76 |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 } | 488 } |
| 488 | 489 |
| 489 | 490 |
| 490 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) { | 491 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 491 if (in_function_) { | 492 if (in_function_) { |
| 492 FAIL(expr, "invalid nested function"); | 493 FAIL(expr, "invalid nested function"); |
| 493 } | 494 } |
| 494 Scope* scope = expr->scope(); | 495 Scope* scope = expr->scope(); |
| 495 DCHECK(scope->is_function_scope()); | 496 DCHECK(scope->is_function_scope()); |
| 496 | 497 |
| 497 if (!expr->bounds().upper->IsFunction()) { | 498 if (!bounds_.get(expr).upper->IsFunction()) { |
| 498 FAIL(expr, "invalid function literal"); | 499 FAIL(expr, "invalid function literal"); |
| 499 } | 500 } |
| 500 | 501 |
| 501 Type* type = expr->bounds().upper; | 502 Type* type = bounds_.get(expr).upper; |
| 502 Type* save_return_type = return_type_; | 503 Type* save_return_type = return_type_; |
| 503 return_type_ = type->AsFunction()->Result(); | 504 return_type_ = type->AsFunction()->Result(); |
| 504 in_function_ = true; | 505 in_function_ = true; |
| 505 local_variable_type_.Clear(); | 506 local_variable_type_.Clear(); |
| 506 RECURSE(VisitDeclarations(scope->declarations())); | 507 RECURSE(VisitDeclarations(scope->declarations())); |
| 507 RECURSE(VisitStatements(expr->body())); | 508 RECURSE(VisitStatements(expr->body())); |
| 508 in_function_ = false; | 509 in_function_ = false; |
| 509 return_type_ = save_return_type; | 510 return_type_ = save_return_type; |
| 510 IntersectResult(expr, type); | 511 IntersectResult(expr, type); |
| 511 } | 512 } |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 if (right == nullptr || right->raw_value()->ContainsDot()) { | 797 if (right == nullptr || right->raw_value()->ContainsDot()) { |
| 797 FAIL(bin->right(), "heap access shift must be integer"); | 798 FAIL(bin->right(), "heap access shift must be integer"); |
| 798 } | 799 } |
| 799 RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, | 800 RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, |
| 800 "array shift expected to be integer")); | 801 "array shift expected to be integer")); |
| 801 int n = static_cast<int>(right->raw_value()->AsNumber()); | 802 int n = static_cast<int>(right->raw_value()->AsNumber()); |
| 802 if (expected_shift < 0 || n != expected_shift) { | 803 if (expected_shift < 0 || n != expected_shift) { |
| 803 FAIL(right, "heap access shift must match element size"); | 804 FAIL(right, "heap access shift must match element size"); |
| 804 } | 805 } |
| 805 } | 806 } |
| 806 expr->key()->set_bounds(Bounds(cache_.kAsmSigned)); | 807 bounds_.set(expr->key(), Bounds(cache_.kAsmSigned)); |
| 807 } | 808 } |
| 808 Type* result_type; | 809 Type* result_type; |
| 809 if (type->Is(cache_.kAsmIntArrayElement)) { | 810 if (type->Is(cache_.kAsmIntArrayElement)) { |
| 810 result_type = cache_.kAsmIntQ; | 811 result_type = cache_.kAsmIntQ; |
| 811 intish_ = kMaxUncombinedAdditiveSteps; | 812 intish_ = kMaxUncombinedAdditiveSteps; |
| 812 } else if (type->Is(cache_.kAsmFloat)) { | 813 } else if (type->Is(cache_.kAsmFloat)) { |
| 813 if (assigning) { | 814 if (assigning) { |
| 814 result_type = cache_.kAsmFloatDoubleQ; | 815 result_type = cache_.kAsmFloatDoubleQ; |
| 815 } else { | 816 } else { |
| 816 result_type = cache_.kAsmFloatQ; | 817 result_type = cache_.kAsmFloatQ; |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 947 FAIL(expr, "invalid property access"); | 948 FAIL(expr, "invalid property access"); |
| 948 } | 949 } |
| 949 | 950 |
| 950 void AsmTyper::CheckPolymorphicStdlibArguments( | 951 void AsmTyper::CheckPolymorphicStdlibArguments( |
| 951 enum StandardMember standard_member, ZoneList<Expression*>* args) { | 952 enum StandardMember standard_member, ZoneList<Expression*>* args) { |
| 952 if (args->length() == 0) { | 953 if (args->length() == 0) { |
| 953 return; | 954 return; |
| 954 } | 955 } |
| 955 // Handle polymorphic stdlib functions specially. | 956 // Handle polymorphic stdlib functions specially. |
| 956 Expression* arg0 = args->at(0); | 957 Expression* arg0 = args->at(0); |
| 957 Type* arg0_type = arg0->bounds().upper; | 958 Type* arg0_type = bounds_.get(arg0).upper; |
| 958 switch (standard_member) { | 959 switch (standard_member) { |
| 959 case kMathFround: { | 960 case kMathFround: { |
| 960 if (!arg0_type->Is(cache_.kAsmFloat) && | 961 if (!arg0_type->Is(cache_.kAsmFloat) && |
| 961 !arg0_type->Is(cache_.kAsmDouble) && | 962 !arg0_type->Is(cache_.kAsmDouble) && |
| 962 !arg0_type->Is(cache_.kAsmSigned) && | 963 !arg0_type->Is(cache_.kAsmSigned) && |
| 963 !arg0_type->Is(cache_.kAsmUnsigned)) { | 964 !arg0_type->Is(cache_.kAsmUnsigned)) { |
| 964 FAIL(arg0, "illegal function argument type"); | 965 FAIL(arg0, "illegal function argument type"); |
| 965 } | 966 } |
| 966 break; | 967 break; |
| 967 } | 968 } |
| 968 case kMathCeil: | 969 case kMathCeil: |
| 969 case kMathFloor: | 970 case kMathFloor: |
| 970 case kMathSqrt: { | 971 case kMathSqrt: { |
| 971 if (!arg0_type->Is(cache_.kAsmFloat) && | 972 if (!arg0_type->Is(cache_.kAsmFloat) && |
| 972 !arg0_type->Is(cache_.kAsmDouble)) { | 973 !arg0_type->Is(cache_.kAsmDouble)) { |
| 973 FAIL(arg0, "illegal function argument type"); | 974 FAIL(arg0, "illegal function argument type"); |
| 974 } | 975 } |
| 975 break; | 976 break; |
| 976 } | 977 } |
| 977 case kMathAbs: | 978 case kMathAbs: |
| 978 case kMathMin: | 979 case kMathMin: |
| 979 case kMathMax: { | 980 case kMathMax: { |
| 980 if (!arg0_type->Is(cache_.kAsmFloat) && | 981 if (!arg0_type->Is(cache_.kAsmFloat) && |
| 981 !arg0_type->Is(cache_.kAsmDouble) && | 982 !arg0_type->Is(cache_.kAsmDouble) && |
| 982 !arg0_type->Is(cache_.kAsmSigned)) { | 983 !arg0_type->Is(cache_.kAsmSigned)) { |
| 983 FAIL(arg0, "illegal function argument type"); | 984 FAIL(arg0, "illegal function argument type"); |
| 984 } | 985 } |
| 985 if (args->length() > 1) { | 986 if (args->length() > 1) { |
| 986 Type* other = Type::Intersect(args->at(0)->bounds().upper, | 987 Type* other = Type::Intersect(bounds_.get(args->at(0)).upper, |
| 987 args->at(1)->bounds().upper, zone()); | 988 bounds_.get(args->at(1)).upper, zone()); |
| 988 if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) && | 989 if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) && |
| 989 !other->Is(cache_.kAsmSigned)) { | 990 !other->Is(cache_.kAsmSigned)) { |
| 990 FAIL(arg0, "function arguments types don't match"); | 991 FAIL(arg0, "function arguments types don't match"); |
| 991 } | 992 } |
| 992 } | 993 } |
| 993 break; | 994 break; |
| 994 } | 995 } |
| 995 default: { break; } | 996 default: { break; } |
| 996 } | 997 } |
| 997 } | 998 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1024 // Checking for asm extern types explicitly, as the type system | 1025 // Checking for asm extern types explicitly, as the type system |
| 1025 // doesn't correctly check their inheritance relationship. | 1026 // doesn't correctly check their inheritance relationship. |
| 1026 if (!computed_type_->Is(cache_.kAsmSigned) && | 1027 if (!computed_type_->Is(cache_.kAsmSigned) && |
| 1027 !computed_type_->Is(cache_.kAsmFixnum) && | 1028 !computed_type_->Is(cache_.kAsmFixnum) && |
| 1028 !computed_type_->Is(cache_.kAsmDouble)) { | 1029 !computed_type_->Is(cache_.kAsmDouble)) { |
| 1029 FAIL(arg, | 1030 FAIL(arg, |
| 1030 "foreign call argument expected to be int, double, or fixnum"); | 1031 "foreign call argument expected to be int, double, or fixnum"); |
| 1031 } | 1032 } |
| 1032 } | 1033 } |
| 1033 intish_ = 0; | 1034 intish_ = 0; |
| 1034 expr->expression()->set_bounds( | 1035 bounds_.set(expr->expression(), |
| 1035 Bounds(Type::Function(Type::Any(), zone()))); | 1036 Bounds(Type::Function(Type::Any(), zone()))); |
| 1036 IntersectResult(expr, expected_type); | 1037 IntersectResult(expr, expected_type); |
| 1037 } else { | 1038 } else { |
| 1038 if (fun_type->Arity() != args->length()) { | 1039 if (fun_type->Arity() != args->length()) { |
| 1039 FAIL(expr, "call with wrong arity"); | 1040 FAIL(expr, "call with wrong arity"); |
| 1040 } | 1041 } |
| 1041 for (int i = 0; i < args->length(); ++i) { | 1042 for (int i = 0; i < args->length(); ++i) { |
| 1042 Expression* arg = args->at(i); | 1043 Expression* arg = args->at(i); |
| 1043 RECURSE(VisitWithExpectation( | 1044 RECURSE(VisitWithExpectation( |
| 1044 arg, fun_type->Parameter(i), | 1045 arg, fun_type->Parameter(i), |
| 1045 "call argument expected to match callee parameter")); | 1046 "call argument expected to match callee parameter")); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 return; | 1192 return; |
| 1192 } | 1193 } |
| 1193 case Token::OR: | 1194 case Token::OR: |
| 1194 case Token::AND: | 1195 case Token::AND: |
| 1195 FAIL(expr, "illegal logical operator"); | 1196 FAIL(expr, "illegal logical operator"); |
| 1196 case Token::BIT_OR: { | 1197 case Token::BIT_OR: { |
| 1197 // BIT_OR allows Any since it is used as a type coercion. | 1198 // BIT_OR allows Any since it is used as a type coercion. |
| 1198 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ, | 1199 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ, |
| 1199 cache_.kAsmSigned, true)); | 1200 cache_.kAsmSigned, true)); |
| 1200 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR && | 1201 if (expr->left()->IsCall() && expr->op() == Token::BIT_OR && |
| 1201 Type::Number()->Is(expr->left()->bounds().upper)) { | 1202 Type::Number()->Is(bounds_.get(expr->left()).upper)) { |
| 1202 // Force the return types of foreign functions. | 1203 // Force the return types of foreign functions. |
| 1203 expr->left()->set_bounds(Bounds(cache_.kAsmSigned)); | 1204 bounds_.set(expr->left(), Bounds(cache_.kAsmSigned)); |
| 1204 } | 1205 } |
| 1205 if (in_function_ && !expr->left()->bounds().upper->Is(cache_.kAsmIntQ)) { | 1206 if (in_function_ && |
| 1207 !bounds_.get(expr->left()).upper->Is(cache_.kAsmIntQ)) { |
| 1206 FAIL(expr->left(), "intish required"); | 1208 FAIL(expr->left(), "intish required"); |
| 1207 } | 1209 } |
| 1208 return; | 1210 return; |
| 1209 } | 1211 } |
| 1210 case Token::BIT_XOR: { | 1212 case Token::BIT_XOR: { |
| 1211 // Handle booleans specially to handle de-sugared ! | 1213 // Handle booleans specially to handle de-sugared ! |
| 1212 Literal* left = expr->left()->AsLiteral(); | 1214 Literal* left = expr->left()->AsLiteral(); |
| 1213 if (left && left->value()->IsBoolean()) { | 1215 if (left && left->value()->IsBoolean()) { |
| 1214 if (left->ToBooleanIsTrue()) { | 1216 if (left->ToBooleanIsTrue()) { |
| 1215 left->set_bounds(Bounds(cache_.kSingletonOne)); | 1217 bounds_.set(left, Bounds(cache_.kSingletonOne)); |
| 1216 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmIntQ, | 1218 RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmIntQ, |
| 1217 "not operator expects an integer")); | 1219 "not operator expects an integer")); |
| 1218 IntersectResult(expr, cache_.kAsmSigned); | 1220 IntersectResult(expr, cache_.kAsmSigned); |
| 1219 return; | 1221 return; |
| 1220 } else { | 1222 } else { |
| 1221 FAIL(left, "unexpected false"); | 1223 FAIL(left, "unexpected false"); |
| 1222 } | 1224 } |
| 1223 } | 1225 } |
| 1224 // BIT_XOR allows Any since it is used as a type coercion (via ~~). | 1226 // BIT_XOR allows Any since it is used as a type coercion (via ~~). |
| 1225 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ, | 1227 RECURSE(VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmIntQ, |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1292 } | 1294 } |
| 1293 IntersectResult(expr, cache_.kAsmInt); | 1295 IntersectResult(expr, cache_.kAsmInt); |
| 1294 return; | 1296 return; |
| 1295 } | 1297 } |
| 1296 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() && | 1298 } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() && |
| 1297 right_type->Is(cache_.kAsmDouble) && | 1299 right_type->Is(cache_.kAsmDouble) && |
| 1298 expr->right()->AsLiteral()->raw_value()->ContainsDot() && | 1300 expr->right()->AsLiteral()->raw_value()->ContainsDot() && |
| 1299 expr->right()->AsLiteral()->raw_value()->AsNumber() == 1.0) { | 1301 expr->right()->AsLiteral()->raw_value()->AsNumber() == 1.0) { |
| 1300 // For unary +, expressed as x * 1.0 | 1302 // For unary +, expressed as x * 1.0 |
| 1301 if (expr->left()->IsCall() && | 1303 if (expr->left()->IsCall() && |
| 1302 Type::Number()->Is(expr->left()->bounds().upper)) { | 1304 Type::Number()->Is(bounds_.get(expr->left()).upper)) { |
| 1303 // Force the return types of foreign functions. | 1305 // Force the return types of foreign functions. |
| 1304 expr->left()->set_bounds(Bounds(cache_.kAsmDouble)); | 1306 bounds_.set(expr->left(), Bounds(cache_.kAsmDouble)); |
| 1305 left_type = expr->left()->bounds().upper; | 1307 left_type = bounds_.get(expr->left()).upper; |
| 1306 } | 1308 } |
| 1307 if (!(expr->left()->IsProperty() && | 1309 if (!(expr->left()->IsProperty() && |
| 1308 Type::Number()->Is(expr->left()->bounds().upper))) { | 1310 Type::Number()->Is(bounds_.get(expr->left()).upper))) { |
| 1309 if (!left_type->Is(cache_.kAsmSigned) && | 1311 if (!left_type->Is(cache_.kAsmSigned) && |
| 1310 !left_type->Is(cache_.kAsmUnsigned) && | 1312 !left_type->Is(cache_.kAsmUnsigned) && |
| 1311 !left_type->Is(cache_.kAsmFixnum) && | 1313 !left_type->Is(cache_.kAsmFixnum) && |
| 1312 !left_type->Is(cache_.kAsmFloatQ) && | 1314 !left_type->Is(cache_.kAsmFloatQ) && |
| 1313 !left_type->Is(cache_.kAsmDoubleQ)) { | 1315 !left_type->Is(cache_.kAsmDoubleQ)) { |
| 1314 FAIL( | 1316 FAIL( |
| 1315 expr->left(), | 1317 expr->left(), |
| 1316 "unary + only allowed on signed, unsigned, float?, or double?"); | 1318 "unary + only allowed on signed, unsigned, float?, or double?"); |
| 1317 } | 1319 } |
| 1318 } | 1320 } |
| 1319 IntersectResult(expr, cache_.kAsmDouble); | 1321 IntersectResult(expr, cache_.kAsmDouble); |
| 1320 return; | 1322 return; |
| 1321 } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmDouble) && | 1323 } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmDouble) && |
| 1322 expr->right()->IsLiteral() && | 1324 expr->right()->IsLiteral() && |
| 1323 !expr->right()->AsLiteral()->raw_value()->ContainsDot() && | 1325 !expr->right()->AsLiteral()->raw_value()->ContainsDot() && |
| 1324 expr->right()->AsLiteral()->raw_value()->AsNumber() == -1.0) { | 1326 expr->right()->AsLiteral()->raw_value()->AsNumber() == -1.0) { |
| 1325 // For unary -, expressed as x * -1 | 1327 // For unary -, expressed as x * -1 |
| 1326 expr->right()->set_bounds(Bounds(cache_.kAsmDouble)); | 1328 bounds_.set(expr->right(), Bounds(cache_.kAsmDouble)); |
| 1327 IntersectResult(expr, cache_.kAsmDouble); | 1329 IntersectResult(expr, cache_.kAsmDouble); |
| 1328 return; | 1330 return; |
| 1329 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { | 1331 } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { |
| 1330 if (left_intish != 0 || right_intish != 0) { | 1332 if (left_intish != 0 || right_intish != 0) { |
| 1331 FAIL(expr, "float operation before required fround"); | 1333 FAIL(expr, "float operation before required fround"); |
| 1332 } | 1334 } |
| 1333 IntersectResult(expr, cache_.kAsmFloat); | 1335 IntersectResult(expr, cache_.kAsmFloat); |
| 1334 intish_ = 1; | 1336 intish_ = 1; |
| 1335 return; | 1337 return; |
| 1336 } else if (type->Is(cache_.kAsmDouble)) { | 1338 } else if (type->Is(cache_.kAsmDouble)) { |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1582 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember( | 1584 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember( |
| 1583 Variable* variable) { | 1585 Variable* variable) { |
| 1584 VariableInfo* info = GetVariableInfo(variable); | 1586 VariableInfo* info = GetVariableInfo(variable); |
| 1585 if (!info) return kNone; | 1587 if (!info) return kNone; |
| 1586 return info->standard_member; | 1588 return info->standard_member; |
| 1587 } | 1589 } |
| 1588 | 1590 |
| 1589 | 1591 |
| 1590 void AsmTyper::SetResult(Expression* expr, Type* type) { | 1592 void AsmTyper::SetResult(Expression* expr, Type* type) { |
| 1591 computed_type_ = type; | 1593 computed_type_ = type; |
| 1592 expr->set_bounds(Bounds(computed_type_)); | 1594 bounds_.set(expr, Bounds(computed_type_)); |
| 1593 } | 1595 } |
| 1594 | 1596 |
| 1595 | 1597 |
| 1596 void AsmTyper::IntersectResult(Expression* expr, Type* type) { | 1598 void AsmTyper::IntersectResult(Expression* expr, Type* type) { |
| 1597 computed_type_ = type; | 1599 computed_type_ = type; |
| 1598 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); | 1600 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); |
| 1599 expr->set_bounds(Bounds(bounded_type)); | 1601 bounds_.set(expr, Bounds(bounded_type)); |
| 1600 } | 1602 } |
| 1601 | 1603 |
| 1602 | 1604 |
| 1603 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type, | 1605 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type, |
| 1604 const char* msg) { | 1606 const char* msg) { |
| 1605 Type* save = expected_type_; | 1607 Type* save = expected_type_; |
| 1606 expected_type_ = expected_type; | 1608 expected_type_ = expected_type; |
| 1607 RECURSE(Visit(expr)); | 1609 RECURSE(Visit(expr)); |
| 1608 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); | 1610 Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone()); |
| 1609 if (bounded_type->Is(Type::None())) { | 1611 if (bounded_type->Is(Type::None())) { |
| 1610 #ifdef DEBUG | 1612 #ifdef DEBUG |
| 1611 PrintF("Computed type: "); | 1613 PrintF("Computed type: "); |
| 1612 computed_type_->Print(); | 1614 computed_type_->Print(); |
| 1613 PrintF("Expected type: "); | 1615 PrintF("Expected type: "); |
| 1614 expected_type_->Print(); | 1616 expected_type_->Print(); |
| 1615 #endif | 1617 #endif |
| 1616 FAIL(expr, msg); | 1618 FAIL(expr, msg); |
| 1617 } | 1619 } |
| 1618 expected_type_ = save; | 1620 expected_type_ = save; |
| 1619 } | 1621 } |
| 1620 | 1622 |
| 1621 | 1623 |
| 1622 void AsmTyper::VisitRewritableExpression(RewritableExpression* expr) { | 1624 void AsmTyper::VisitRewritableExpression(RewritableExpression* expr) { |
| 1623 RECURSE(Visit(expr->expression())); | 1625 RECURSE(Visit(expr->expression())); |
| 1624 } | 1626 } |
| 1625 | 1627 |
| 1626 | 1628 |
| 1627 } // namespace internal | 1629 } // namespace internal |
| 1628 } // namespace v8 | 1630 } // namespace v8 |
| OLD | NEW |