[wasm] Refactor handling of variable info in typing-asm.cc

R=bradnelson@chromium.org,rossberg@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/1951013002
Cr-Commit-Position: refs/heads/master@{#36052}
This commit is contained in:
titzer 2016-05-05 12:07:32 -07:00 committed by Commit bot
parent e8c7592c5e
commit 87cbbdfb1e
2 changed files with 103 additions and 100 deletions

View File

@ -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) {
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) {
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 entry ? reinterpret_cast<VariableInfo*>(entry->value) : nullptr;
}
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::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;
}

View File

@ -151,7 +151,8 @@ class AsmTyper : public AstVisitor {
void SetType(Variable* variable, Type* type);
Type* GetType(Variable* variable);
VariableInfo* GetVariableInfo(Variable* variable, bool setting);
VariableInfo* GetVariableInfo(Variable* variable);
VariableInfo* MakeVariableInfo(Variable* variable);
void SetVariableInfo(Variable* variable, const VariableInfo* info);
VariableInfo* LibType(ObjectTypeMap* map, Handle<String> name);
@ -165,8 +166,6 @@ class AsmTyper : public AstVisitor {
void VisitLiteral(Literal* expr, bool is_return);
void VisitVariableProxy(VariableProxy* expr, bool assignment);
void VisitIntegerBitwiseOperator(BinaryOperation* expr, Type* left_expected,
Type* right_expected, Type* result_type,
bool conversion);