Chromium Code Reviews| Index: src/typing-asm.cc |
| diff --git a/src/typing-asm.cc b/src/typing-asm.cc |
| index 771d255b81a5ba81eb1865ac49cff3e370f8b8f0..9a8cf8f1bf3b9c55314ba5218638c64052a3ba15 100644 |
| --- a/src/typing-asm.cc |
| +++ b/src/typing-asm.cc |
| @@ -44,7 +44,7 @@ AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script, |
| root_(root), |
| valid_(true), |
| allow_simd_(false), |
| - property_info_(NULL), |
| + property_info_(nullptr), |
| intish_(0), |
| stdlib_types_(zone), |
| stdlib_heap_types_(zone), |
| @@ -79,16 +79,16 @@ void AsmTyper::VisitAsmModule(FunctionLiteral* fun) { |
| if (!scope->is_function_scope()) FAIL(fun, "not at function scope"); |
| ExpressionStatement* use_asm = fun->body()->first()->AsExpressionStatement(); |
| - if (use_asm == NULL) FAIL(fun, "missing \"use asm\""); |
| + if (use_asm == nullptr) FAIL(fun, "missing \"use asm\""); |
| Literal* use_asm_literal = use_asm->expression()->AsLiteral(); |
| - if (use_asm_literal == NULL) FAIL(fun, "missing \"use asm\""); |
| + if (use_asm_literal == nullptr) FAIL(fun, "missing \"use asm\""); |
| if (!use_asm_literal->raw_value()->AsString()->IsOneByteEqualTo("use asm")) |
| FAIL(fun, "missing \"use asm\""); |
| // Module parameters. |
| for (int i = 0; i < scope->num_parameters(); ++i) { |
| Variable* param = scope->parameter(i); |
| - DCHECK(GetType(param) == NULL); |
| + DCHECK(GetType(param) == nullptr); |
| SetType(param, Type::None()); |
| } |
| @@ -96,7 +96,7 @@ void AsmTyper::VisitAsmModule(FunctionLiteral* fun) { |
| // Set all globals to type Any. |
| VariableDeclaration* decl = scope->function(); |
| - if (decl != NULL) SetType(decl->proxy()->var(), Type::None()); |
| + if (decl != nullptr) SetType(decl->proxy()->var(), Type::None()); |
| RECURSE(VisitDeclarations(scope->declarations())); |
| // Validate global variables. |
| @@ -105,15 +105,15 @@ void AsmTyper::VisitAsmModule(FunctionLiteral* fun) { |
| // Validate function annotations. |
| for (int i = 0; i < decls->length(); ++i) { |
| FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration(); |
| - if (decl != NULL) { |
| + if (decl != nullptr) { |
| RECURSE(VisitFunctionAnnotation(decl->fun())); |
| Variable* var = decl->proxy()->var(); |
| - if (property_info_ != NULL) { |
| + if (property_info_ != nullptr) { |
| SetVariableInfo(var, property_info_); |
| - property_info_ = NULL; |
| + property_info_ = nullptr; |
| } |
| SetType(var, computed_type_); |
| - DCHECK(GetType(var) != NULL); |
| + DCHECK(GetType(var) != nullptr); |
| } |
| } |
| @@ -125,7 +125,7 @@ void AsmTyper::VisitAsmModule(FunctionLiteral* fun) { |
| // Validate function bodies. |
| for (int i = 0; i < decls->length(); ++i) { |
| FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration(); |
| - if (decl != NULL) { |
| + if (decl != nullptr) { |
| RECURSE(VisitWithExpectation(decl->fun(), Type::Any(), "UNREACHABLE")); |
| if (!computed_type_->IsFunction()) { |
| FAIL(decl->fun(), "function literal expected to be a function"); |
| @@ -147,13 +147,13 @@ void AsmTyper::VisitAsmModule(FunctionLiteral* fun) { |
| void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) { |
| Variable* var = decl->proxy()->var(); |
| if (var->location() != VariableLocation::PARAMETER) { |
| - if (GetType(var) == NULL) { |
| + if (GetType(var) == nullptr) { |
| SetType(var, Type::Any()); |
| } else { |
| DCHECK(!GetType(var)->IsFunction()); |
| } |
| } |
| - DCHECK(GetType(var) != NULL); |
| + DCHECK(GetType(var) != nullptr); |
| intish_ = 0; |
| } |
| @@ -175,14 +175,14 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
| Type* result_type = Type::Undefined(); |
| if (body->length() > 0) { |
| ReturnStatement* stmt = body->last()->AsReturnStatement(); |
| - if (stmt != NULL) { |
| + if (stmt != nullptr) { |
| Literal* literal = stmt->expression()->AsLiteral(); |
| Type* old_expected = expected_type_; |
| expected_type_ = Type::Any(); |
| if (literal) { |
| RECURSE(VisitLiteral(literal, true)); |
| } else { |
| - RECURSE(VisitExpressionAnnotation(stmt->expression(), NULL, true)); |
| + RECURSE(VisitExpressionAnnotation(stmt->expression(), nullptr, true)); |
| } |
| expected_type_ = old_expected; |
| result_type = computed_type_; |
| @@ -197,18 +197,18 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) { |
| good = false; |
| if (i >= body->length()) break; |
| ExpressionStatement* stmt = body->at(i)->AsExpressionStatement(); |
| - if (stmt == NULL) break; |
| + if (stmt == nullptr) break; |
| Assignment* expr = stmt->expression()->AsAssignment(); |
| - if (expr == NULL || expr->is_compound()) break; |
| + if (expr == nullptr || expr->is_compound()) break; |
| VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| - if (proxy == NULL) break; |
| + if (proxy == nullptr) break; |
| Variable* var = proxy->var(); |
| if (var->location() != VariableLocation::PARAMETER || var->index() != i) |
| break; |
| RECURSE(VisitExpressionAnnotation(expr->value(), var, false)); |
| - if (property_info_ != NULL) { |
| + if (property_info_ != nullptr) { |
| SetVariableInfo(var, property_info_); |
| - property_info_ = NULL; |
| + property_info_ = nullptr; |
| } |
| SetType(var, computed_type_); |
| type->AsFunction()->InitParameter(i, computed_type_); |
| @@ -224,10 +224,10 @@ 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) { |
| + if (bin != nullptr) { |
| + if (var != nullptr) { |
| VariableProxy* proxy = bin->left()->AsVariableProxy(); |
| - if (proxy == NULL) { |
| + if (proxy == nullptr) { |
| FAIL(bin->left(), "expected variable for type annotation"); |
| } |
| if (proxy->var() != var) { |
| @@ -235,7 +235,7 @@ void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var, |
| } |
| } |
| Literal* right = bin->right()->AsLiteral(); |
| - if (right != NULL) { |
| + if (right != nullptr) { |
| switch (bin->op()) { |
| case Token::MUL: // We encode +x as x*1.0 |
| if (right->raw_value()->ContainsDot() && |
| @@ -269,10 +269,10 @@ void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var, |
| } |
| Call* call = expr->AsCall(); |
| - if (call != NULL) { |
| + if (call != nullptr) { |
| VariableProxy* proxy = call->expression()->AsVariableProxy(); |
| - if (proxy != NULL) { |
| - VariableInfo* info = GetVariableInfo(proxy->var(), false); |
| + if (proxy != nullptr) { |
| + VariableInfo* info = GetVariableInfo(proxy->var()); |
| if (!info || |
| (!info->is_check_function && !info->is_constructor_function)) { |
| if (allow_simd_) { |
| @@ -448,14 +448,14 @@ void AsmTyper::VisitForStatement(ForStatement* stmt) { |
| if (!in_function_) { |
| FAIL(stmt, "for statement inside module body"); |
| } |
| - if (stmt->init() != NULL) { |
| + if (stmt->init() != nullptr) { |
| RECURSE(Visit(stmt->init())); |
| } |
| - if (stmt->cond() != NULL) { |
| + if (stmt->cond() != nullptr) { |
| RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned, |
| "for condition expected to be integer")); |
| } |
| - if (stmt->next() != NULL) { |
| + if (stmt->next() != nullptr) { |
| RECURSE(Visit(stmt->next())); |
| } |
| RECURSE(Visit(stmt->body())); |
| @@ -556,40 +556,31 @@ 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_) { |
| + VariableInfo* info = GetVariableInfo(var); |
| + if (!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 (info == nullptr || info->type == nullptr) { |
| if (var->mode() == TEMPORARY) { |
| SetType(var, Type::Any()); |
| - info = GetVariableInfo(var, false); |
| + info = GetVariableInfo(var); |
| } else { |
| FAIL(expr, "unbound variable"); |
| } |
| } |
| - if (property_info_ != NULL) { |
| + if (property_info_ != nullptr) { |
| SetVariableInfo(var, property_info_); |
| - property_info_ = NULL; |
| + property_info_ = nullptr; |
| } |
| Type* type = Type::Intersect(info->type, expected_type_, zone()); |
| - if (type->Is(cache_.kAsmInt)) { |
| - type = cache_.kAsmInt; |
| - } |
| - info->type = type; |
| + if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt; |
| intish_ = 0; |
| IntersectResult(expr, type); |
| } |
| - |
| void AsmTyper::VisitLiteral(Literal* expr, bool is_return) { |
| intish_ = 0; |
| Handle<Object> value = expr->value(); |
| @@ -683,13 +674,35 @@ void AsmTyper::VisitAssignment(Assignment* expr) { |
| RECURSE(VisitWithExpectation( |
| expr->value(), type, "assignment value expected to match surrounding")); |
| Type* target_type = StorageType(computed_type_); |
| + |
| if (expr->target()->IsVariableProxy()) { |
| + // Assignment to a local or context variable. |
| + VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| if (intish_ != 0) { |
| FAIL(expr, "intish or floatish assignment"); |
| } |
| expected_type_ = target_type; |
| - VisitVariableProxy(expr->target()->AsVariableProxy(), true); |
| + Variable* var = proxy->var(); |
| + VariableInfo* info = GetVariableInfo(var); |
| + if (info == nullptr || info->type == nullptr) { |
|
bradnelson
2016/05/05 04:21:58
Structurally equivalent, but probably can be reduc
|
| + if (var->mode() == TEMPORARY) { |
| + SetType(var, Type::Any()); |
| + info = GetVariableInfo(var); |
| + } else { |
| + FAIL(proxy, "unbound variable"); |
| + } |
| + } |
| + if (property_info_ != nullptr) { |
| + SetVariableInfo(var, property_info_); |
| + property_info_ = nullptr; |
| + } |
| + Type* type = Type::Intersect(info->type, expected_type_, zone()); |
| + if (type->Is(cache_.kAsmInt)) type = cache_.kAsmInt; |
| + info->type = type; |
| + intish_ = 0; |
| + IntersectResult(proxy, type); |
| } else if (expr->target()->IsProperty()) { |
| + // Assignment to a property: should be a heap assignment {H[x] = y}. |
| int32_t value_intish = intish_; |
| Property* property = expr->target()->AsProperty(); |
| RECURSE(VisitWithExpectation(property->obj(), Type::Any(), |
| @@ -745,13 +758,13 @@ void AsmTyper::VisitHeapAccess(Property* expr, bool assigning, |
| } |
| // TODO(bradnelson): Fix the parser and then un-comment this part |
| // BinaryOperation* bin = expr->key()->AsBinaryOperation(); |
| - // if (bin == NULL || bin->op() != Token::BIT_AND) { |
| + // if (bin == nullptr || bin->op() != Token::BIT_AND) { |
| // FAIL(expr->key(), "expected & in call"); |
| // } |
| // RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, |
| // "array index expected to be integer")); |
| // Literal* right = bin->right()->AsLiteral(); |
| - // if (right == NULL || right->raw_value()->ContainsDot()) { |
| + // if (right == nullptr || right->raw_value()->ContainsDot()) { |
| // FAIL(right, "call mask must be integer"); |
| // } |
| // RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, |
| @@ -774,13 +787,13 @@ void AsmTyper::VisitHeapAccess(Property* expr, bool assigning, |
| RECURSE(Visit(expr->key())); |
| } else { |
| BinaryOperation* bin = expr->key()->AsBinaryOperation(); |
| - if (bin == NULL || bin->op() != Token::SAR) { |
| + if (bin == nullptr || bin->op() != Token::SAR) { |
| FAIL(expr->key(), "expected >> in heap access"); |
| } |
| RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned, |
| "array index expected to be integer")); |
| Literal* right = bin->right()->AsLiteral(); |
| - if (right == NULL || right->raw_value()->ContainsDot()) { |
| + if (right == nullptr || right->raw_value()->ContainsDot()) { |
| FAIL(bin->right(), "heap access shift must be integer"); |
| } |
| RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned, |
| @@ -830,18 +843,18 @@ void AsmTyper::VisitHeapAccess(Property* expr, bool assigning, |
| bool AsmTyper::IsStdlibObject(Expression* expr) { |
| VariableProxy* proxy = expr->AsVariableProxy(); |
| - if (proxy == NULL) { |
| + if (proxy == nullptr) { |
| return false; |
| } |
| Variable* var = proxy->var(); |
| - VariableInfo* info = GetVariableInfo(var, false); |
| + VariableInfo* info = GetVariableInfo(var); |
| if (info) { |
| if (info->standard_member == kStdlib) return true; |
| } |
| if (var->location() != VariableLocation::PARAMETER || var->index() != 0) { |
| return false; |
| } |
| - info = GetVariableInfo(var, true); |
| + info = MakeVariableInfo(var); |
| info->type = Type::Object(); |
| info->standard_member = kStdlib; |
| return true; |
| @@ -851,13 +864,13 @@ bool AsmTyper::IsStdlibObject(Expression* expr) { |
| Expression* AsmTyper::GetReceiverOfPropertyAccess(Expression* expr, |
| const char* name) { |
| Property* property = expr->AsProperty(); |
| - if (property == NULL) { |
| - return NULL; |
| + if (property == nullptr) { |
| + return nullptr; |
| } |
| Literal* key = property->key()->AsLiteral(); |
| - if (key == NULL || !key->IsPropertyName() || |
| + if (key == nullptr || !key->IsPropertyName() || |
| !key->AsPropertyName()->IsUtf8EqualTo(CStrVector(name))) { |
| - return NULL; |
| + return nullptr; |
| } |
| return property->obj(); |
| } |
| @@ -904,7 +917,7 @@ void AsmTyper::VisitProperty(Property* expr) { |
| return; |
| } |
| - property_info_ = NULL; |
| + property_info_ = nullptr; |
| // Only recurse at this point so that we avoid needing |
| // stdlib.Math to have a real type. |
| @@ -913,12 +926,12 @@ void AsmTyper::VisitProperty(Property* expr) { |
| // For heap view or function table access. |
| if (computed_type_->IsArray()) { |
| - VisitHeapAccess(expr, false, NULL); |
| + VisitHeapAccess(expr, false, nullptr); |
| return; |
| } |
| VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
| - if (proxy != NULL) { |
| + if (proxy != nullptr) { |
| Variable* var = proxy->var(); |
| if (var->location() == VariableLocation::PARAMETER && var->index() == 1) { |
| // foreign.x - Function represent as () -> Any |
| @@ -992,10 +1005,10 @@ void AsmTyper::VisitCall(Call* expr) { |
| if (proxy) { |
| standard_member = VariableAsStandardMember(proxy->var()); |
| } |
| - if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) { |
| + if (!in_function_ && (proxy == nullptr || standard_member != kMathFround)) { |
| FAIL(expr, "calls forbidden outside function bodies"); |
| } |
| - if (proxy == NULL && !expr->expression()->IsProperty()) { |
| + if (proxy == nullptr && !expr->expression()->IsProperty()) { |
| FAIL(expr, "calls must be to bound variables or function tables"); |
| } |
| if (computed_type_->IsFunction()) { |
| @@ -1502,11 +1515,12 @@ void AsmTyper::InitializeStdlib() { |
| void AsmTyper::VisitLibraryAccess(ObjectTypeMap* map, Property* expr) { |
| Literal* key = expr->key()->AsLiteral(); |
| - if (key == NULL || !key->IsPropertyName()) |
| + if (key == nullptr || !key->IsPropertyName()) |
| FAIL(expr, "invalid key used on stdlib member"); |
| Handle<String> name = key->AsPropertyName(); |
| VariableInfo* info = LibType(map, name); |
| - if (info == NULL || info->type == NULL) FAIL(expr, "unknown stdlib function"); |
| + if (info == nullptr || info->type == nullptr) |
| + FAIL(expr, "unknown stdlib function"); |
| SetResult(expr, info->type); |
| property_info_ = info; |
| } |
| @@ -1517,57 +1531,47 @@ AsmTyper::VariableInfo* AsmTyper::LibType(ObjectTypeMap* map, |
| base::SmartArrayPointer<char> aname = name->ToCString(); |
| ObjectTypeMap::iterator i = map->find(std::string(aname.get())); |
| if (i == map->end()) { |
| - return NULL; |
| + return nullptr; |
| } |
| return i->second; |
| } |
| void AsmTyper::SetType(Variable* variable, Type* type) { |
| - VariableInfo* info = GetVariableInfo(variable, true); |
| + VariableInfo* info = MakeVariableInfo(variable); |
| info->type = type; |
| } |
| Type* AsmTyper::GetType(Variable* variable) { |
| - VariableInfo* info = GetVariableInfo(variable, false); |
| - if (!info) return NULL; |
| + VariableInfo* info = GetVariableInfo(variable); |
| + if (!info) return nullptr; |
| return info->type; |
| } |
| - |
| -AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable, |
| - bool setting) { |
| - ZoneHashMap::Entry* entry; |
| - ZoneHashMap* map; |
| - if (in_function_) { |
| - map = &local_variable_type_; |
| - } else { |
| - map = &global_variable_type_; |
| - } |
| - if (setting) { |
| - entry = map->LookupOrInsert(variable, ComputePointerHash(variable), |
| - ZoneAllocationPolicy(zone())); |
| - } else { |
| - entry = map->Lookup(variable, ComputePointerHash(variable)); |
| - if (!entry && in_function_) { |
| - entry = |
| - global_variable_type_.Lookup(variable, ComputePointerHash(variable)); |
| - if (entry && entry->value) { |
| - } |
| - } |
| - } |
| - if (!entry) return NULL; |
| - if (!entry->value) { |
| - if (!setting) return NULL; |
| - entry->value = new (zone()) VariableInfo; |
| +AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable) { |
| + ZoneHashMap* map = |
| + in_function_ ? &local_variable_type_ : &global_variable_type_; |
| + ZoneHashMap::Entry* entry = |
| + map->Lookup(variable, ComputePointerHash(variable)); |
| + if (!entry && in_function_) { |
| + entry = |
| + global_variable_type_.Lookup(variable, ComputePointerHash(variable)); |
| } |
| - return reinterpret_cast<VariableInfo*>(entry->value); |
| + return entry ? reinterpret_cast<VariableInfo*>(entry->value) : nullptr; |
| } |
| +AsmTyper::VariableInfo* AsmTyper::MakeVariableInfo(Variable* variable) { |
| + ZoneHashMap* map = |
| + in_function_ ? &local_variable_type_ : &global_variable_type_; |
| + ZoneHashMap::Entry* entry = map->LookupOrInsert( |
| + variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone())); |
| + if (!entry->value) entry->value = new (zone()) VariableInfo; |
| + return reinterpret_cast<VariableInfo*>(entry->value); |
| +} |
| void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) { |
| - VariableInfo* dest = GetVariableInfo(variable, true); |
| + VariableInfo* dest = MakeVariableInfo(variable); |
| dest->type = info->type; |
| dest->is_check_function = info->is_check_function; |
| dest->is_constructor_function = info->is_constructor_function; |
| @@ -1577,7 +1581,7 @@ void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) { |
| AsmTyper::StandardMember AsmTyper::VariableAsStandardMember( |
| Variable* variable) { |
| - VariableInfo* info = GetVariableInfo(variable, false); |
| + VariableInfo* info = GetVariableInfo(variable); |
| if (!info) return kNone; |
| return info->standard_member; |
| } |