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

Unified Diff: runtime/vm/code_generator_ia32.cc

Issue 10051011: Eliminate type checks that can successfully be performed at compile time. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 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 | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/code_generator_x64.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/code_generator_ia32.cc
===================================================================
--- runtime/vm/code_generator_ia32.cc (revision 6419)
+++ runtime/vm/code_generator_ia32.cc (working copy)
@@ -667,7 +667,7 @@
}
if (FLAG_trace_functions) {
const Function& function =
- Function::ZoneHandle(parsed_function_.function().raw());
+ Function::ZoneHandle(parsed_function_.function().raw());
__ LoadObject(EBX, function);
__ pushl(EAX); // Preserve result.
__ pushl(EBX);
@@ -723,8 +723,6 @@
// Generate type check.
if (FLAG_enable_type_checks) {
- const bool returns_null = node->value()->IsLiteralNode() &&
- node->value()->AsLiteralNode()->literal().IsNull();
const RawFunction::Kind kind = parsed_function().function().kind();
const bool is_implicit_getter =
(kind == RawFunction::kImplicitGetter) ||
@@ -732,10 +730,11 @@
const bool is_static = parsed_function().function().is_static();
// Implicit getters do not need a type check at return, unless they compute
// the initial value of a static field.
- if (!returns_null && (is_static || !is_implicit_getter)) {
+ if (is_static || !is_implicit_getter) {
GenerateAssertAssignable(
node->id(),
node->value()->token_index(),
+ node->value(),
AbstractType::ZoneHandle(parsed_function().function().result_type()),
String::ZoneHandle(String::NewSymbol("function result")));
}
@@ -762,6 +761,7 @@
__ popl(EAX);
GenerateAssertAssignable(node->id(),
node->token_index(),
+ node->expr(),
node->type(),
node->dst_name());
if (IsResultNeeded(node)) {
@@ -971,6 +971,7 @@
if (FLAG_enable_type_checks) {
GenerateAssertAssignable(node->id(),
node->value()->token_index(),
+ node->value(),
node->local().type(),
node->local().name());
}
@@ -1000,6 +1001,7 @@
if (FLAG_enable_type_checks) {
GenerateAssertAssignable(node->id(),
node->value()->token_index(),
+ node->value(),
AbstractType::ZoneHandle(node->field().type()),
String::ZoneHandle(node->field().name()));
}
@@ -1103,6 +1105,7 @@
if (FLAG_enable_type_checks) {
GenerateAssertAssignable(node->id(),
node->value()->token_index(),
+ node->value(),
AbstractType::ZoneHandle(node->field().type()),
String::ZoneHandle(node->field().name()));
}
@@ -1189,6 +1192,7 @@
if (FLAG_enable_type_checks) {
GenerateAssertAssignable(node->id(),
node->token_index(),
+ NULL,
node->local().type(),
node->local().name());
}
@@ -1281,7 +1285,8 @@
}
-// Optimize instanceof type test by adding inlined tests for:
+// If instanceof type test cannot be performed successfully at compile time and
+// therefore eliminated, optimize it by adding inlined tests for:
// - NULL -> return false.
// - Smi -> compile time subtype check (only if dst class is not parameterized).
// - Class equality (only if class is not parameterized).
@@ -1292,13 +1297,14 @@
// - true or false on stack.
void CodeGenerator::GenerateInstanceOf(intptr_t node_id,
intptr_t token_index,
+ AstNode* value,
const AbstractType& type,
bool negate_result) {
ASSERT(type.IsFinalized() && !type.IsMalformed());
const Bool& bool_true = Bool::ZoneHandle(Bool::True());
const Bool& bool_false = Bool::ZoneHandle(Bool::False());
- // All instances are of a subtype of the Object type.
+ // All objects are instances of type T if Object type is a subtype of type T.
const Type& object_type =
Type::Handle(Isolate::Current()->object_store()->object_type());
Error& malformed_error = Error::Handle();
@@ -1308,6 +1314,33 @@
return;
}
+ // Eliminate the test if it can be performed successfully at compile time.
+ if ((value != NULL) && value->IsLiteralNode() && type.IsInstantiated()) {
+ const Instance& literal_value = value->AsLiteralNode()->literal();
+ const Class& cls = Class::Handle(literal_value.clazz());
+ if (cls.IsNullClass()) {
+ ASSERT(literal_value.IsNull() ||
+ (literal_value.raw() == Object::sentinel()) ||
+ (literal_value.raw() == Object::transition_sentinel()));
+ // A null object is only an instance of Object and Dynamic, which has
+ // already been checked above (if the type is instantiated). So we can
+ // return false here if the instance is null (and if the type is
+ // instantiated).
+ __ PushObject(negate_result ? bool_true : bool_false);
+ } else {
+ Error& malformed_error = Error::Handle();
+ if (literal_value.IsInstanceOf(type,
+ TypeArguments::Handle(),
+ &malformed_error)) {
+ __ PushObject(negate_result ? bool_false : bool_true);
+ } else {
+ ASSERT(malformed_error.IsNull());
+ __ PushObject(negate_result ? bool_true : bool_false);
+ }
+ }
+ return;
+ }
+
const Immediate raw_null =
Immediate(reinterpret_cast<intptr_t>(Object::null()));
Label done, check_negate_done;
@@ -1488,7 +1521,8 @@
}
-// Optimize assignable type check by adding inlined tests for:
+// If type check cannot be performed successfully at compile time and therefore
+// eliminated, optimize it by adding inlined tests for:
// - NULL -> return NULL.
// - Smi -> compile time subtype check (only if dst class is not parameterized).
// - Class equality (only if class is not parameterized).
@@ -1501,6 +1535,7 @@
// as they throw an exception.
void CodeGenerator::GenerateAssertAssignable(intptr_t node_id,
intptr_t token_index,
+ AstNode* value,
const AbstractType& dst_type,
const String& dst_name) {
ASSERT(FLAG_enable_type_checks);
@@ -1524,6 +1559,26 @@
return;
}
+ // Eliminate the test if it can be performed successfully at compile time.
+ if ((value != NULL) && value->IsLiteralNode()) {
+ const Instance& literal_value = value->AsLiteralNode()->literal();
+ const Class& cls = Class::Handle(literal_value.clazz());
+ if (cls.IsNullClass()) {
+ ASSERT(literal_value.IsNull() ||
+ (literal_value.raw() == Object::sentinel()) ||
+ (literal_value.raw() == Object::transition_sentinel()));
+ return;
+ }
+ Error& malformed_error = Error::Handle();
+ if (!dst_type.IsMalformed() &&
+ dst_type.IsInstantiated() &&
+ literal_value.IsInstanceOf(dst_type,
+ TypeArguments::Handle(),
+ &malformed_error)) {
+ return;
+ }
+ }
+
// A null object is always assignable and is returned as result.
const Immediate raw_null =
Immediate(reinterpret_cast<intptr_t>(Object::null()));
@@ -1748,6 +1803,7 @@
GenerateLoadVariable(EAX, *parameter);
GenerateAssertAssignable(AstNode::kNoId,
parameter->token_index(),
+ NULL,
parameter->type(),
parameter->name());
}
@@ -1804,6 +1860,7 @@
ASSERT(node->right()->IsTypeNode());
GenerateInstanceOf(node->id(),
node->token_index(),
+ node->left(),
node->right()->AsTypeNode()->type(),
(node->kind() == Token::kISNOT));
if (!IsResultNeeded(node)) {
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/code_generator_x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698