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

Unified Diff: src/typing-asm.cc

Issue 1473513004: Refactor VisitProperty, add starting point for SIMD.js support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: merge Created 5 years, 1 month 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 ebb5eaa67f3f34c26103b4ef60bb4cb6b6193e18..be74193597ef3c9f7bb8d96ca597ca6186e6d8f7 100644
--- a/src/typing-asm.cc
+++ b/src/typing-asm.cc
@@ -38,16 +38,22 @@ namespace internal {
AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
FunctionLiteral* root)
: zone_(zone),
+ isolate_(isolate),
script_(script),
root_(root),
valid_(true),
+ allow_simd_(false),
intish_(0),
stdlib_types_(zone),
stdlib_heap_types_(zone),
stdlib_math_types_(zone),
- global_variable_type_(HashMap::PointersMatch,
- ZoneHashMap::kDefaultHashMapCapacity,
- ZoneAllocationPolicy(zone)),
+#define V(NAME, Name, name, lane_count, lane_type) \
+ stdlib_simd_##name##_types_(zone),
+ SIMD128_TYPES(V)
+#undef V
+ global_variable_type_(HashMap::PointersMatch,
+ ZoneHashMap::kDefaultHashMapCapacity,
+ ZoneAllocationPolicy(zone)),
local_variable_type_(HashMap::PointersMatch,
ZoneHashMap::kDefaultHashMapCapacity,
ZoneAllocationPolicy(zone)),
@@ -93,6 +99,10 @@ void AsmTyper::VisitAsmModule(FunctionLiteral* fun) {
RECURSE(VisitFunctionAnnotation(decl->fun()));
Variable* var = decl->proxy()->var();
DCHECK(GetType(var) == NULL);
+ if (property_info_ != NULL) {
+ SetVariableInfo(var, property_info_);
+ property_info_ = NULL;
+ }
SetType(var, computed_type_);
DCHECK(GetType(var) != NULL);
}
@@ -181,6 +191,10 @@ void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) {
if (var->location() != VariableLocation::PARAMETER || var->index() != i)
break;
RECURSE(VisitExpressionAnnotation(expr->value(), var, false));
+ if (property_info_ != NULL) {
+ SetVariableInfo(var, property_info_);
+ property_info_ = NULL;
+ }
SetType(var, computed_type_);
type->InitParameter(i, computed_type_);
good = true;
@@ -197,12 +211,12 @@ void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var,
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");
+ VariableProxy* proxy = bin->left()->AsVariableProxy();
+ if (proxy == NULL) {
+ FAIL(bin->left(), "expected variable for type annotation");
}
- if (left->var() != var) {
- FAIL(left, "variable type annotation references other variable");
+ if (proxy->var() != var) {
+ FAIL(proxy, "annotation source doesn't match destination");
}
}
Literal* right = bin->right()->AsLiteral();
@@ -241,19 +255,28 @@ void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var,
Call* call = expr->AsCall();
if (call != NULL) {
- if (call->expression()->IsVariableProxy()) {
- RECURSE(VisitWithExpectation(
- call->expression(), Type::Any(zone()),
- "only fround allowed on expression annotations"));
- if (!computed_type_->Is(
- Type::Function(cache_.kAsmFloat, Type::Number(zone()), zone()))) {
- FAIL(call->expression(),
- "only fround allowed on expression annotations");
+ VariableProxy* proxy = call->expression()->AsVariableProxy();
+ if (proxy != NULL) {
+ VariableInfo* info = GetVariableInfo(proxy->var(), false);
+ if (!info ||
+ (!info->is_check_function && !info->is_constructor_function)) {
+ if (allow_simd_) {
+ FAIL(call->expression(),
+ "only fround/SIMD.checks allowed on expression annotations");
+ } else {
+ FAIL(call->expression(),
+ "only fround allowed on expression annotations");
+ }
}
- if (call->arguments()->length() != 1) {
- FAIL(call, "invalid argument count calling fround");
+ Type* type = info->type;
+ DCHECK(type->IsFunction());
+ if (info->is_check_function) {
+ DCHECK(type->AsFunction()->Arity() == 1);
}
- SetResult(expr, cache_.kAsmFloat);
+ if (call->arguments()->length() != type->AsFunction()->Arity()) {
+ FAIL(call, "invalid argument count calling function");
+ }
+ SetResult(expr, type->AsFunction()->Result());
return;
}
}
@@ -499,10 +522,15 @@ void AsmTyper::VisitConditional(Conditional* expr) {
void AsmTyper::VisitVariableProxy(VariableProxy* expr) {
Variable* var = expr->var();
- if (GetType(var) == NULL) {
+ VariableInfo* info = GetVariableInfo(var, false);
+ if (info == NULL || info->type == NULL) {
FAIL(expr, "unbound variable");
}
- Type* type = Type::Intersect(GetType(var), expected_type_, zone());
+ if (property_info_ != NULL) {
+ SetVariableInfo(var, property_info_);
+ property_info_ = NULL;
+ }
+ Type* type = Type::Intersect(info->type, expected_type_, zone());
if (type->Is(cache_.kAsmInt)) {
type = cache_.kAsmInt;
}
@@ -739,35 +767,83 @@ void AsmTyper::VisitHeapAccess(Property* expr, bool assigning,
}
-void AsmTyper::VisitProperty(Property* expr) {
- // stdlib.Math.x
- Property* inner_prop = expr->obj()->AsProperty();
- if (inner_prop != NULL) {
- // Get property name.
- Literal* key = expr->key()->AsLiteral();
- if (key == NULL || !key->IsPropertyName())
- FAIL(expr, "invalid type annotation on property 2");
- Handle<String> name = key->AsPropertyName();
-
- // Check that inner property name is "Math".
- Literal* math_key = inner_prop->key()->AsLiteral();
- if (math_key == NULL || !math_key->IsPropertyName() ||
- !math_key->AsPropertyName()->IsUtf8EqualTo(CStrVector("Math")))
- FAIL(expr, "invalid type annotation on stdlib (a1)");
-
- // Check that object is stdlib.
- VariableProxy* proxy = inner_prop->obj()->AsVariableProxy();
- if (proxy == NULL) FAIL(expr, "invalid type annotation on stdlib (a2)");
- Variable* var = proxy->var();
- if (var->location() != VariableLocation::PARAMETER || var->index() != 0)
- FAIL(expr, "invalid type annotation on stdlib (a3)");
+bool AsmTyper::IsStdlibObject(Expression* expr) {
+ VariableProxy* proxy = expr->AsVariableProxy();
+ if (proxy == NULL) {
+ return false;
+ }
+ Variable* var = proxy->var();
+ VariableInfo* info = GetVariableInfo(var, false);
+ if (info) {
+ if (info->is_stdlib_object) return info->is_stdlib_object;
+ }
+ if (var->location() != VariableLocation::PARAMETER || var->index() != 0) {
+ return false;
+ }
+ info = GetVariableInfo(var, true);
+ info->type = Type::Object();
+ info->is_stdlib_object = true;
+ return true;
+}
+
+
+Expression* AsmTyper::GetReceiverOfPropertyAccess(Expression* expr,
+ const char* name) {
+ Property* property = expr->AsProperty();
+ if (property == NULL) {
+ return NULL;
+ }
+ Literal* key = property->key()->AsLiteral();
+ if (key == NULL || !key->IsPropertyName() ||
+ !key->AsPropertyName()->IsUtf8EqualTo(CStrVector(name))) {
+ return NULL;
+ }
+ return property->obj();
+}
+
+
+bool AsmTyper::IsMathObject(Expression* expr) {
+ Expression* obj = GetReceiverOfPropertyAccess(expr, "Math");
+ return obj && IsStdlibObject(obj);
+}
+
+
+bool AsmTyper::IsSIMDObject(Expression* expr) {
+ Expression* obj = GetReceiverOfPropertyAccess(expr, "SIMD");
+ return obj && IsStdlibObject(obj);
+}
+
- // Look up library type.
- Type* type = LibType(stdlib_math_types_, name);
- if (type == NULL) FAIL(expr, "unknown standard function 3 ");
- SetResult(expr, type);
+bool AsmTyper::IsSIMDTypeObject(Expression* expr, const char* name) {
+ Expression* obj = GetReceiverOfPropertyAccess(expr, name);
+ return obj && IsSIMDObject(obj);
+}
+
+
+void AsmTyper::VisitProperty(Property* expr) {
+ if (IsMathObject(expr->obj())) {
+ VisitLibraryAccess(&stdlib_math_types_, expr);
return;
}
+#define V(NAME, Name, name, lane_count, lane_type) \
+ if (IsSIMDTypeObject(expr->obj(), #Name)) { \
+ VisitLibraryAccess(&stdlib_simd_##name##_types_, expr); \
+ return; \
+ } \
+ if (IsSIMDTypeObject(expr, #Name)) { \
+ VariableInfo* info = stdlib_simd_##name##_constructor_type_; \
+ SetResult(expr, info->type); \
+ property_info_ = info; \
+ return; \
+ }
+ SIMD128_TYPES(V)
+#undef V
+ if (IsStdlibObject(expr->obj())) {
+ VisitLibraryAccess(&stdlib_types_, expr);
+ return;
+ }
+
+ property_info_ = NULL;
// Only recurse at this point so that we avoid needing
// stdlib.Math to have a real type.
@@ -779,35 +855,14 @@ void AsmTyper::VisitProperty(Property* expr) {
return;
}
- // Get property name.
- Literal* key = expr->key()->AsLiteral();
- if (key == NULL || !key->IsPropertyName())
- FAIL(expr, "invalid type annotation on property 3");
- Handle<String> name = key->AsPropertyName();
-
// stdlib.x or foreign.x
VariableProxy* proxy = expr->obj()->AsVariableProxy();
if (proxy != NULL) {
Variable* var = proxy->var();
- if (var->location() != VariableLocation::PARAMETER) {
- FAIL(expr, "invalid type annotation on variable");
- }
- switch (var->index()) {
- case 0: {
- // Object is stdlib, look up library type.
- Type* type = LibType(stdlib_types_, name);
- if (type == NULL) {
- FAIL(expr, "unknown standard function 4");
- }
- SetResult(expr, type);
- return;
- }
- case 1:
- // Object is foreign lib.
- SetResult(expr, expected_type_);
- return;
- default:
- FAIL(expr, "invalid type annotation on parameter");
+ if (var->location() == VariableLocation::PARAMETER && var->index() == 1) {
+ // foreign.x is ok.
+ SetResult(expr, expected_type_);
+ return;
}
}
@@ -1143,7 +1198,26 @@ 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()); \
+ for (int i = 0; i < lane_count; ++i) { \
+ type->AsFunction()->InitParameter(i, Type::Number()); \
+ } \
+ stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \
+ stdlib_simd_##name##_constructor_type_->is_constructor_function = true; \
+ }
+ SIMD128_TYPES(V)
+#undef V
+}
+
+
void AsmTyper::InitializeStdlib() {
+ if (allow_simd_) {
+ InitializeStdlibSIMD();
+ }
Type* number_type = Type::Number(zone());
Type* double_type = cache_.kAsmDouble;
Type* double_fn1_type = Type::Function(double_type, double_type, zone());
@@ -1177,30 +1251,44 @@ void AsmTyper::InitializeStdlib() {
{"acos", double_fn1_type}, {"asin", double_fn1_type},
{"atan", double_fn1_type}, {"atan2", double_fn2_type}};
for (unsigned i = 0; i < arraysize(math); ++i) {
- stdlib_math_types_[math[i].name] = math[i].type;
+ stdlib_math_types_[math[i].name] = new (zone()) VariableInfo(math[i].type);
}
+ stdlib_math_types_["fround"]->is_check_function = true;
- stdlib_types_["Infinity"] = double_type;
- stdlib_types_["NaN"] = double_type;
+ stdlib_types_["Infinity"] = new (zone()) VariableInfo(double_type);
+ stdlib_types_["NaN"] = new (zone()) VariableInfo(double_type);
Type* buffer_type = Type::Any(zone());
#define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
- stdlib_types_[#TypeName "Array"] = \
- Type::Function(cache_.k##TypeName##Array, buffer_type, zone());
+ stdlib_types_[#TypeName "Array"] = new (zone()) VariableInfo( \
+ Type::Function(cache_.k##TypeName##Array, buffer_type, zone()));
TYPED_ARRAYS(TYPED_ARRAY)
#undef TYPED_ARRAY
-#define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
- stdlib_heap_types_[#TypeName "Array"] = \
- Type::Function(cache_.k##TypeName##Array, buffer_type, zone());
+#define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
+ stdlib_heap_types_[#TypeName "Array"] = new (zone()) VariableInfo( \
+ Type::Function(cache_.k##TypeName##Array, buffer_type, zone()));
TYPED_ARRAYS(TYPED_ARRAY)
#undef TYPED_ARRAY
}
-Type* AsmTyper::LibType(ObjectTypeMap map, Handle<String> name) {
+void AsmTyper::VisitLibraryAccess(ObjectTypeMap* map, Property* expr) {
+ Literal* key = expr->key()->AsLiteral();
+ if (key == NULL || !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");
+ SetResult(expr, info->type);
+ property_info_ = info;
+}
+
+
+AsmTyper::VariableInfo* AsmTyper::LibType(ObjectTypeMap* map,
+ Handle<String> name) {
base::SmartArrayPointer<char> aname = name->ToCString();
- ObjectTypeMap::iterator i = map.find(std::string(aname.get()));
- if (i == map.end()) {
+ ObjectTypeMap::iterator i = map->find(std::string(aname.get()));
+ if (i == map->end()) {
return NULL;
}
return i->second;
@@ -1208,32 +1296,52 @@ Type* AsmTyper::LibType(ObjectTypeMap map, Handle<String> name) {
void AsmTyper::SetType(Variable* variable, Type* type) {
- ZoneHashMap::Entry* entry;
- if (in_function_) {
- entry = local_variable_type_.LookupOrInsert(
- variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone()));
- } else {
- entry = global_variable_type_.LookupOrInsert(
- variable, ComputePointerHash(variable), ZoneAllocationPolicy(zone()));
- }
- entry->value = reinterpret_cast<void*>(type);
+ VariableInfo* info = GetVariableInfo(variable, true);
+ info->type = type;
}
Type* AsmTyper::GetType(Variable* variable) {
- i::ZoneHashMap::Entry* entry = NULL;
+ VariableInfo* info = GetVariableInfo(variable, false);
+ if (!info) return NULL;
+ return info->type;
+}
+
+
+AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable,
+ bool setting) {
+ ZoneHashMap::Entry* entry;
+ ZoneHashMap* map;
if (in_function_) {
- entry = local_variable_type_.Lookup(variable, ComputePointerHash(variable));
- }
- if (entry == NULL) {
- entry =
- global_variable_type_.Lookup(variable, ComputePointerHash(variable));
+ map = &local_variable_type_;
+ } else {
+ map = &global_variable_type_;
}
- if (entry == NULL) {
- return NULL;
+ if (setting) {
+ entry = map->LookupOrInsert(variable, ComputePointerHash(variable),
+ ZoneAllocationPolicy(zone()));
} else {
- return reinterpret_cast<Type*>(entry->value);
+ entry = map->Lookup(variable, ComputePointerHash(variable));
+ if (!entry && in_function_) {
+ entry =
+ global_variable_type_.Lookup(variable, ComputePointerHash(variable));
+ }
}
+ if (!entry) return NULL;
+ if (!entry->value) {
+ if (!setting) return NULL;
+ entry->value = new (zone()) VariableInfo;
+ }
+ return reinterpret_cast<VariableInfo*>(entry->value);
+}
+
+
+void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) {
+ VariableInfo* dest = GetVariableInfo(variable, true);
+ dest->type = info->type;
+ dest->is_stdlib_object = info->is_stdlib_object;
+ dest->is_check_function = info->is_check_function;
+ dest->is_constructor_function = info->is_constructor_function;
}
« 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