Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: src/typing-asm.cc

Issue 1968383002: Remove Expression::bounds_, in order to conserve memory during parsing. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove Expression::bounds_ Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/typing-asm.h ('k') | src/v8.gyp » ('j') | test/cctest/test-ast-expression-visitor.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698