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

Unified Diff: src/typing-asm.cc

Issue 1643003004: Accurately type foreign functions, and variables (attempt 2). (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: pass zone Created 4 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/typing-asm.h ('k') | test/cctest/test-asm-validator.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/typing-asm.cc
diff --git a/src/typing-asm.cc b/src/typing-asm.cc
index 14db16ba94b36aeba4e97dfd503ee061f1000e4c..c17e19b33a40ff957f9cd749f54570b7f2cedd33 100644
--- a/src/typing-asm.cc
+++ b/src/typing-asm.cc
@@ -36,7 +36,6 @@ namespace internal {
if (!valid_) return; \
} while (false)
-
AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
FunctionLiteral* root)
: zone_(zone),
@@ -62,6 +61,7 @@ AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
ZoneAllocationPolicy(zone)),
in_function_(false),
building_function_tables_(false),
+ visiting_exports_(false),
cache_(TypeCache::Get()) {
InitializeAstVisitor(isolate);
InitializeStdlib();
@@ -135,6 +135,7 @@ void AsmTyper::VisitAsmModule(FunctionLiteral* fun) {
}
// Validate exports.
+ visiting_exports_ = true;
ReturnStatement* stmt = fun->body()->last()->AsReturnStatement();
if (stmt == nullptr) {
FAIL(fun->body()->last(), "last statement in module is not a return");
@@ -178,7 +179,7 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) {
if (stmt != NULL) {
Literal* literal = stmt->expression()->AsLiteral();
Type* old_expected = expected_type_;
- expected_type_ = Type::Any();
+ expected_type_ = Type::Any(zone());
if (literal) {
RECURSE(VisitLiteral(literal, true));
} else {
@@ -188,9 +189,9 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) {
result_type = computed_type_;
}
}
- Type::FunctionType* type =
- Type::Function(result_type, Type::Any(), fun->parameter_count(), zone())
- ->AsFunction();
+ Type::FunctionType* type = Type::Function(result_type, Type::Any(zone()),
+ fun->parameter_count(), zone())
+ ->AsFunction();
// Extract parameter types.
bool good = true;
@@ -265,7 +266,7 @@ void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var,
// Numbers or the undefined literal (for empty returns).
if (expr->IsLiteral()) {
- RECURSE(VisitWithExpectation(expr, Type::Any(), "invalid literal"));
+ RECURSE(VisitWithExpectation(expr, Type::Any(zone()), "invalid literal"));
return;
}
@@ -315,7 +316,7 @@ void AsmTyper::VisitBlock(Block* stmt) {
void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
- RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(),
+ RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(zone()),
"expression statement expected to be any"));
}
@@ -367,7 +368,7 @@ void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) {
VisitLiteral(literal, true);
} else {
RECURSE(
- VisitWithExpectation(stmt->expression(), Type::Any(),
+ VisitWithExpectation(stmt->expression(), Type::Any(zone()),
"return expression expected to have return type"));
}
if (!computed_type_->Is(return_type_) || !return_type_->Is(computed_type_)) {
@@ -489,11 +490,11 @@ void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
- Scope* scope = expr->scope();
- DCHECK(scope->is_function_scope());
if (in_function_) {
FAIL(expr, "invalid nested function");
}
+ Scope* scope = expr->scope();
+ DCHECK(scope->is_function_scope());
if (!expr->bounds().upper->IsFunction()) {
FAIL(expr, "invalid function literal");
@@ -523,7 +524,10 @@ void AsmTyper::VisitDoExpression(DoExpression* expr) {
void AsmTyper::VisitConditional(Conditional* expr) {
- RECURSE(VisitWithExpectation(expr->condition(), Type::Number(),
+ if (!in_function_) {
+ FAIL(expr, "ternary operator inside module body");
+ }
+ RECURSE(VisitWithExpectation(expr->condition(), Type::Number(zone()),
"condition expected to be integer"));
if (!computed_type_->Is(cache_.kAsmInt)) {
FAIL(expr->condition(), "condition must be of type int");
@@ -554,8 +558,18 @@ void AsmTyper::VisitConditional(Conditional* expr) {
void AsmTyper::VisitVariableProxy(VariableProxy* expr) {
+ VisitVariableProxy(expr, false);
+}
+
+void AsmTyper::VisitVariableProxy(VariableProxy* expr, bool assignment) {
Variable* var = expr->var();
VariableInfo* info = GetVariableInfo(var, false);
+ if (!assignment && !in_function_ && !building_function_tables_ &&
+ !visiting_exports_) {
+ if (var->location() != VariableLocation::PARAMETER || var->index() >= 3) {
+ FAIL(expr, "illegal variable reference in module body");
+ }
+ }
if (info == NULL || info->type == NULL) {
if (var->mode() == TEMPORARY) {
SetType(var, Type::Any(zone()));
@@ -642,7 +656,7 @@ void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) {
Type* elem_type = Type::None(zone());
for (int i = 0; i < values->length(); ++i) {
Expression* value = values->at(i);
- RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE"));
+ RECURSE(VisitWithExpectation(value, Type::Any(zone()), "UNREACHABLE"));
if (!computed_type_->IsFunction()) {
FAIL(value, "array component expected to be a function");
}
@@ -675,11 +689,11 @@ void AsmTyper::VisitAssignment(Assignment* expr) {
FAIL(expr, "intish or floatish assignment");
}
if (expr->target()->IsVariableProxy()) {
- RECURSE(VisitWithExpectation(expr->target(), target_type,
- "assignment target expected to match value"));
+ expected_type_ = target_type;
+ VisitVariableProxy(expr->target()->AsVariableProxy(), true);
} else if (expr->target()->IsProperty()) {
Property* property = expr->target()->AsProperty();
- RECURSE(VisitWithExpectation(property->obj(), Type::Any(),
+ RECURSE(VisitWithExpectation(property->obj(), Type::Any(zone()),
"bad propety object"));
if (!computed_type_->IsArray()) {
FAIL(property->obj(), "array expected");
@@ -888,7 +902,8 @@ void AsmTyper::VisitProperty(Property* expr) {
// Only recurse at this point so that we avoid needing
// stdlib.Math to have a real type.
- RECURSE(VisitWithExpectation(expr->obj(), Type::Any(), "bad propety object"));
+ RECURSE(VisitWithExpectation(expr->obj(), Type::Any(zone()),
+ "bad propety object"));
// For heap view or function table access.
if (computed_type_->IsArray()) {
@@ -912,7 +927,8 @@ void AsmTyper::VisitProperty(Property* expr) {
void AsmTyper::VisitCall(Call* expr) {
- RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
+ Type* expected_type = expected_type_;
+ RECURSE(VisitWithExpectation(expr->expression(), Type::Any(zone()),
"callee expected to be any"));
StandardMember standard_member = kNone;
VariableProxy* proxy = expr->expression()->AsVariableProxy();
@@ -967,16 +983,24 @@ void AsmTyper::VisitCall(Call* expr) {
}
intish_ = 0;
IntersectResult(expr, result_type);
- } else if (computed_type_->Is(Type::Any())) {
+ } else if (computed_type_->Is(Type::Any(zone()))) {
// For foreign calls.
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
- RECURSE(VisitWithExpectation(arg, Type::Any(),
+ RECURSE(VisitWithExpectation(arg, Type::Any(zone()),
"foreign call argument expected to be any"));
+ // Checking for asm extern types explicitly, as the type system
+ // doesn't correctly check their inheritance relationship.
+ if (!computed_type_->Is(cache_.kAsmSigned) &&
+ !computed_type_->Is(cache_.kAsmFixnum) &&
+ !computed_type_->Is(cache_.kAsmDouble)) {
+ FAIL(arg,
+ "foreign call argument expected to be int, double, or fixnum");
+ }
}
intish_ = kMaxUncombinedAdditiveSteps;
- IntersectResult(expr, Type::Number());
+ IntersectResult(expr, expected_type);
} else {
FAIL(expr, "invalid callee");
}
@@ -987,7 +1011,7 @@ void AsmTyper::VisitCallNew(CallNew* expr) {
if (in_function_) {
FAIL(expr, "new not allowed in module function");
}
- RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
+ RECURSE(VisitWithExpectation(expr->expression(), Type::Any(zone()),
"expected stdlib function"));
if (computed_type_->IsFunction()) {
Type::FunctionType* fun_type = computed_type_->AsFunction();
@@ -1014,6 +1038,9 @@ void AsmTyper::VisitCallRuntime(CallRuntime* expr) {
void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) {
+ if (!in_function_) {
+ FAIL(expr, "unary operator inside module body");
+ }
switch (expr->op()) {
case Token::NOT: // Used to encode != and !==
RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt,
@@ -1041,7 +1068,7 @@ void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
Type* left_expected,
Type* right_expected,
Type* result_type, bool conversion) {
- RECURSE(VisitWithExpectation(expr->left(), Type::Number(),
+ RECURSE(VisitWithExpectation(expr->left(), Type::Number(zone()),
"left bitwise operand expected to be a number"));
int left_intish = intish_;
Type* left_type = computed_type_;
@@ -1053,7 +1080,7 @@ void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
}
RECURSE(
- VisitWithExpectation(expr->right(), Type::Number(),
+ VisitWithExpectation(expr->right(), Type::Number(zone()),
"right bitwise operand expected to be a number"));
int right_intish = intish_;
Type* right_type = computed_type_;
@@ -1082,11 +1109,20 @@ void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
+ if (!in_function_) {
+ if (expr->op() != Token::BIT_OR && expr->op() != Token::MUL) {
+ FAIL(expr, "illegal binary operator inside module body");
+ }
+ if (!(expr->left()->IsProperty() || expr->left()->IsVariableProxy()) ||
+ !expr->right()->IsLiteral()) {
+ FAIL(expr, "illegal computation inside module body");
+ }
+ }
switch (expr->op()) {
case Token::COMMA: {
- RECURSE(VisitWithExpectation(expr->left(), Type::Any(),
+ RECURSE(VisitWithExpectation(expr->left(), Type::Any(zone()),
"left comma operand expected to be any"));
- RECURSE(VisitWithExpectation(expr->right(), Type::Any(),
+ RECURSE(VisitWithExpectation(expr->right(), Type::Any(zone()),
"right comma operand expected to be any"));
IntersectResult(expr, computed_type_);
return;
@@ -1096,8 +1132,11 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
FAIL(expr, "illegal logical operator");
case Token::BIT_OR: {
// BIT_OR allows Any since it is used as a type coercion.
- VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmInt,
+ VisitIntegerBitwiseOperator(expr, Type::Any(zone()), cache_.kAsmInt,
cache_.kAsmSigned, true);
+ if (expr->left()->IsCall() && expr->op() == Token::BIT_OR) {
+ IntersectResult(expr->left(), cache_.kAsmSigned);
+ }
return;
}
case Token::BIT_XOR: {
@@ -1115,7 +1154,7 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
}
}
// BIT_XOR allows Number since it is used as a type coercion (via ~~).
- VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kAsmInt,
+ VisitIntegerBitwiseOperator(expr, Type::Number(zone()), cache_.kAsmInt,
cache_.kAsmSigned, true);
return;
}
@@ -1137,12 +1176,12 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
case Token::DIV:
case Token::MOD: {
RECURSE(VisitWithExpectation(
- expr->left(), Type::Number(),
+ expr->left(), Type::Number(zone()),
"left arithmetic operand expected to be number"));
Type* left_type = computed_type_;
int left_intish = intish_;
RECURSE(VisitWithExpectation(
- expr->right(), Type::Number(),
+ expr->right(), Type::Number(zone()),
"right arithmetic operand expected to be number"));
Type* right_type = computed_type_;
int right_intish = intish_;
@@ -1184,6 +1223,9 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
} else if (expr->op() == Token::MUL && expr->right()->IsLiteral() &&
right_type->Is(cache_.kAsmDouble)) {
// For unary +, expressed as x * 1.0
+ if (expr->left()->IsCall() && expr->op() == Token::MUL) {
+ IntersectResult(expr->left(), cache_.kAsmDouble);
+ }
IntersectResult(expr, cache_.kAsmDouble);
return;
} else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) {
@@ -1207,6 +1249,9 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
void AsmTyper::VisitCompareOperation(CompareOperation* expr) {
+ if (!in_function_) {
+ FAIL(expr, "comparison inside module body");
+ }
Token::Value op = expr->op();
if (op != Token::EQ && op != Token::NE && op != Token::LT &&
op != Token::LTE && op != Token::GT && op != Token::GTE) {
@@ -1214,7 +1259,7 @@ void AsmTyper::VisitCompareOperation(CompareOperation* expr) {
}
RECURSE(
- VisitWithExpectation(expr->left(), Type::Number(),
+ VisitWithExpectation(expr->left(), Type::Number(zone()),
"left comparison operand expected to be number"));
Type* left_type = computed_type_;
if (!left_type->Is(cache_.kAsmComparable)) {
@@ -1222,7 +1267,7 @@ void AsmTyper::VisitCompareOperation(CompareOperation* expr) {
}
RECURSE(
- VisitWithExpectation(expr->right(), Type::Number(),
+ VisitWithExpectation(expr->right(), Type::Number(zone()),
"right comparison operand expected to be number"));
Type* right_type = computed_type_;
if (!right_type->Is(cache_.kAsmComparable)) {
@@ -1281,10 +1326,10 @@ void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) {
void AsmTyper::InitializeStdlibSIMD() {
#define V(NAME, Name, name, lane_count, lane_type) \
{ \
- Type* type = Type::Function(Type::Name(isolate_, zone()), Type::Any(), \
- lane_count, zone()); \
+ Type* type = Type::Function(Type::Name(isolate_, zone()), \
+ Type::Any(zone()), lane_count, zone()); \
for (int i = 0; i < lane_count; ++i) { \
- type->AsFunction()->InitParameter(i, Type::Number()); \
+ type->AsFunction()->InitParameter(i, Type::Number(zone())); \
} \
stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \
stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \
« no previous file with comments | « src/typing-asm.h ('k') | test/cctest/test-asm-validator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698