Chromium Code Reviews| Index: src/typing-asm.cc |
| diff --git a/src/typing-asm.cc b/src/typing-asm.cc |
| index da752418a63ba63e53b3c9e781c86817be7d60f0..3ebae9408aa13f9ec600af69a06bd97508b014bf 100644 |
| --- a/src/typing-asm.cc |
| +++ b/src/typing-asm.cc |
| @@ -41,6 +41,8 @@ AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, |
| script_(script), |
| root_(root), |
| valid_(true), |
| + intish_(0), |
| + assigning_(false), |
| stdlib_types_(zone), |
| stdlib_heap_types_(zone), |
| stdlib_math_types_(zone), |
| @@ -155,7 +157,7 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
| if (literal) { |
| RECURSE(VisitLiteral(literal, true)); |
| } else { |
| - RECURSE(VisitExpressionAnnotation(stmt->expression(), true)); |
| + RECURSE(VisitExpressionAnnotation(stmt->expression(), NULL, true)); |
| } |
| expected_type_ = old_expected; |
| result_type = computed_type_; |
| @@ -179,7 +181,7 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
| Variable* var = proxy->var(); |
| if (var->location() != VariableLocation::PARAMETER || var->index() != i) |
| break; |
| - RECURSE(VisitExpressionAnnotation(expr->value(), false)); |
| + RECURSE(VisitExpressionAnnotation(expr->value(), var, false)); |
| SetType(var, computed_type_); |
| type->InitParameter(i, computed_type_); |
| good = true; |
| @@ -190,10 +192,20 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
| } |
| -void AsmTyper::VisitExpressionAnnotation(Expression* expr, bool is_return) { |
| +void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var, |
| + bool is_return) { |
| // Normal +x or x|0 annotations. |
| BinaryOperation* bin = expr->AsBinaryOperation(); |
| if (bin != NULL) { |
| + if (var != NULL) { |
| + VariableProxy* left = bin->left()->AsVariableProxy(); |
| + if (!left) { |
| + FAIL(expr, "variable name expected in type annotation"); |
| + } |
| + if (left->var() != var) { |
| + FAIL(left, "variable type annotation references other variable"); |
| + } |
| + } |
| Literal* right = bin->right()->AsLiteral(); |
| if (right != NULL) { |
| switch (bin->op()) { |
| @@ -497,6 +509,7 @@ void AsmTyper::VisitVariableProxy(VariableProxy* expr) { |
| } |
| SetType(var, type); |
| intish_ = 0; |
| + assigning_ = false; |
| IntersectResult(expr, type); |
| } |
| @@ -593,18 +606,14 @@ void AsmTyper::VisitAssignment(Assignment* expr) { |
| Type* type = expected_type_; |
| RECURSE(VisitWithExpectation( |
| expr->value(), type, "assignment value expected to match surrounding")); |
| + Type* target_type = StorageType(computed_type_); |
| if (intish_ != 0) { |
| - FAIL(expr, "value still an intish"); |
| - } |
| - Type* target_type = computed_type_; |
| - if (target_type->Is(cache_.kAsmInt)) { |
| - target_type = cache_.kAsmInt; |
| + FAIL(expr, "intish or floatish assignment"); |
| } |
| + assigning_ = true; |
|
titzer
2015/11/24 07:32:32
At first glance this follow a stack discipline, bu
bradn
2015/11/30 20:34:44
So it turns out the spec allows nested assignment,
|
| RECURSE(VisitWithExpectation(expr->target(), target_type, |
| "assignment target expected to match value")); |
| - if (intish_ != 0) { |
| - FAIL(expr, "value still an intish"); |
| - } |
| + DCHECK(!assigning_); |
| IntersectResult(expr, computed_type_); |
| } |
| @@ -658,6 +667,7 @@ void AsmTyper::VisitHeapAccess(Property* expr) { |
| FAIL(right, "call mask must match function table"); |
| } |
| bin->set_bounds(Bounds(cache_.kAsmSigned)); |
| + IntersectResult(expr, type); |
| } else { |
| Literal* literal = expr->key()->AsLiteral(); |
| if (literal) { |
| @@ -683,8 +693,34 @@ void AsmTyper::VisitHeapAccess(Property* expr) { |
| } |
| bin->set_bounds(Bounds(cache_.kAsmSigned)); |
| } |
| + Type* result_type; |
| + if (type->Is(cache_.kAsmIntArrayElement)) { |
| + result_type = cache_.kAsmIntQ; |
| + intish_ = kMaxUncombinedAdditiveSteps; |
| + } else if (type->Is(cache_.kAsmFloat)) { |
| + if (assigning_) { |
| + result_type = cache_.kAsmFloatDoubleQ; |
| + } else { |
| + result_type = cache_.kAsmFloatQ; |
| + } |
| + intish_ = 0; |
| + } else if (type->Is(cache_.kAsmDouble)) { |
| + if (assigning_) { |
| + result_type = cache_.kAsmFloatDoubleQ; |
| + if (intish_ != 0) { |
| + FAIL(expr, "Assignment of floatish to Float64Array"); |
| + } |
| + } else { |
| + result_type = cache_.kAsmDoubleQ; |
| + } |
| + intish_ = 0; |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + IntersectResult(expr, expected_type_); |
| + IntersectResult(expr, result_type); |
| + assigning_ = false; |
| } |
| - IntersectResult(expr, type); |
| } |
| @@ -780,6 +816,7 @@ void AsmTyper::VisitCall(Call* expr) { |
| arg, fun_type->Parameter(i), |
| "call argument expected to match callee parameter")); |
| } |
| + intish_ = 0; |
| IntersectResult(expr, fun_type->Result()); |
| } else if (computed_type_->Is(Type::Any())) { |
| // For foreign calls. |
| @@ -789,6 +826,7 @@ void AsmTyper::VisitCall(Call* expr) { |
| RECURSE(VisitWithExpectation(arg, Type::Any(), |
| "foreign call argument expected to be any")); |
| } |
| + intish_ = kMaxUncombinedAdditiveSteps; |
| IntersectResult(expr, Type::Number()); |
| } else { |
| FAIL(expr, "invalid callee"); |
| @@ -994,13 +1032,17 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) { |
| IntersectResult(expr, cache_.kAsmInt); |
| return; |
| } |
| - } else if (expr->op() == Token::MUL && left_type->Is(cache_.kAsmInt) && |
| + } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() && |
| right_type->Is(cache_.kAsmDouble)) { |
| // For unary +, expressed as x * 1.0 |
| IntersectResult(expr, cache_.kAsmDouble); |
| return; |
| } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) { |
| + if (left_intish != 0 || right_intish != 0) { |
| + FAIL(expr, "float operation before required fround"); |
| + } |
| IntersectResult(expr, cache_.kAsmFloat); |
| + intish_ = 1; |
| return; |
| } else if (type->Is(cache_.kAsmDouble)) { |
| IntersectResult(expr, cache_.kAsmDouble); |