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

Unified Diff: runtime/vm/flow_graph_compiler_ia32.cc

Issue 10466006: Implemented in ia32: branch, strict compare, instance setter, instanceof and assertassigneable with… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 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/flow_graph_compiler_ia32.h ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_compiler_ia32.cc
===================================================================
--- runtime/vm/flow_graph_compiler_ia32.cc (revision 8254)
+++ runtime/vm/flow_graph_compiler_ia32.cc (working copy)
@@ -7,6 +7,7 @@
#include "vm/flow_graph_compiler.h"
+#include "lib/error.h"
#include "vm/ast_printer.h"
#include "vm/compiler_stats.h"
#include "vm/il_printer.h"
@@ -408,6 +409,179 @@
}
+// 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).
+// Inputs:
+// - EAX: object.
+// - EDX: instantiator type arguments or raw_null.
+// - ECX: instantiator or raw_null.
+// Returns:
+// - true or false in EAX.
+void FlowGraphCompiler::GenerateInstanceOf(intptr_t cid,
+ intptr_t token_index,
+ intptr_t try_index,
+ 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());
+
+ const Immediate raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ Label is_instance, is_not_instance;
+ __ pushl(ECX); // Store instantiator on stack.
+ __ pushl(EDX); // Store instantiator type arguments.
+ // If type is instantiated and non-parameterized, we can inline code
+ // checking whether the tested instance is a Smi.
+ if (type.IsInstantiated()) {
+ // 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).
+ // We can only inline this null check if the type is instantiated at compile
+ // time, since an uninstantiated type at compile time could be Object or
+ // Dynamic at run time.
+ __ cmpl(EAX, raw_null);
+ __ j(EQUAL, &is_not_instance);
+ }
+ // TODO(srdjan): Enable inlined checks.
+ // Generate inline instanceof test.
+ SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+ // test_cache = GenerateInlineInstanceof(cid, token_index, type,
+ // &is_instance, &is_not_instance);
+
+ // Generate runtime call.
+ __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
+ __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
+ __ PushObject(Object::ZoneHandle()); // Make room for the result.
+ __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
+ __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
+ __ pushl(EAX); // Push the instance.
+ __ PushObject(type); // Push the type.
+ __ pushl(ECX); // TODO(srdjan): Pass instantiator instead of null.
+ __ pushl(EDX); // Instantiator type arguments.
+ __ LoadObject(EAX, test_cache);
+ __ pushl(EAX);
+ GenerateCallRuntime(cid, token_index, try_index, kInstanceofRuntimeEntry);
+ // Pop the two parameters supplied to the runtime entry. The result of the
+ // instanceof runtime call will be left as the result of the operation.
+ __ Drop(7);
+ Label done;
+ if (negate_result) {
+ __ popl(EDX);
+ __ LoadObject(EAX, bool_true);
+ __ cmpl(EDX, EAX);
+ __ j(NOT_EQUAL, &done, Assembler::kNearJump);
+ __ LoadObject(EAX, bool_false);
+ } else {
+ __ popl(EAX);
+ }
+ __ jmp(&done, Assembler::kNearJump);
+
+ __ Bind(&is_not_instance);
+ __ LoadObject(EAX, negate_result ? bool_true : bool_false);
+ __ jmp(&done, Assembler::kNearJump);
+
+ __ Bind(&is_instance);
+ __ LoadObject(EAX, negate_result ? bool_false : bool_true);
+ __ Bind(&done);
+ __ popl(EDX); // Remove pushed instantiator type arguments.
+ __ popl(ECX); // Remove pushed instantiator.
+}
+
+
+// Optimize assignable type check 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).
+// Inputs:
+// - EAX: object.
+// - EDX: instantiator type arguments or raw_null.
+// - ECX: instantiator or raw_null.
+// Returns:
+// - object in EAX for successful assignable check (or throws TypeError).
+// Performance notes: positive checks must be quick, negative checks can be slow
+// as they throw an exception.
+void FlowGraphCompiler::GenerateAssertAssignable(intptr_t cid,
+ intptr_t token_index,
+ intptr_t try_index,
+ const AbstractType& dst_type,
+ const String& dst_name) {
+ ASSERT(FLAG_enable_type_checks);
+ ASSERT(token_index >= 0);
+ ASSERT(!dst_type.IsNull());
+ ASSERT(dst_type.IsFinalized());
+ // Assignable check is skipped in FlowGraphBuilder, not here.
+ ASSERT(dst_type.IsMalformed() ||
+ (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
+ ASSERT(!dst_type.IsVoidType());
+ __ pushl(ECX); // Store instantiator.
+ __ pushl(EDX); // Store instantiator type arguments.
+ // A null object is always assignable and is returned as result.
+ const Immediate raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ Label is_assignable, runtime_call;
+ __ cmpl(EAX, raw_null);
+ __ j(EQUAL, &is_assignable);
+
+ // Generate throw new TypeError() if the type is malformed.
+ if (dst_type.IsMalformed()) {
+ const Error& error = Error::Handle(dst_type.malformed_error());
+ const String& error_message = String::ZoneHandle(
+ String::NewSymbol(error.ToErrorCString()));
+ __ PushObject(Object::ZoneHandle()); // Make room for the result.
+ __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
+ __ pushl(EAX); // Push the source object.
+ __ PushObject(dst_name); // Push the name of the destination.
+ __ PushObject(error_message);
+ GenerateCallRuntime(cid,
+ token_index,
+ try_index,
+ kMalformedTypeErrorRuntimeEntry);
+ // We should never return here.
+ __ int3();
+
+ __ Bind(&is_assignable); // For a null object.
+ return;
+ }
+
+ // TODO(srdjan): Enable subtype test cache.
+ // Generate inline type check, linking to runtime call if not assignable.
+ SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
+ // test_cache = GenerateInlineInstanceof(cid, token_index, dst_type,
+ // &is_assignable, &runtime_call);
+
+ __ Bind(&runtime_call);
+ __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
+ __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
+ __ PushObject(Object::ZoneHandle()); // Make room for the result.
+ __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
+ __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
+ __ pushl(EAX); // Push the source object.
+ __ PushObject(dst_type); // Push the type of the destination.
+ __ pushl(ECX); // Instantiator.
+ __ pushl(EDX); // Instantiator type arguments.
+ __ PushObject(dst_name); // Push the name of the destination.
+ __ LoadObject(EAX, test_cache);
+ __ pushl(EAX);
+ GenerateCallRuntime(cid,
+ token_index,
+ try_index,
+ kTypeCheckRuntimeEntry);
+ // Pop the parameters supplied to the runtime entry. The result of the
+ // type check runtime call is the checked value.
+ __ Drop(8);
+ __ popl(EAX);
+
+ __ Bind(&is_assignable);
+ __ popl(EDX); // Remove pushed instantiator type arguments..
+ __ popl(ECX); // Remove pushed instantiator.
+}
+
+
void FlowGraphCompiler::EmitComment(Instruction* instr) {
char buffer[80];
BufferFormatter f(buffer, sizeof(buffer));
« no previous file with comments | « runtime/vm/flow_graph_compiler_ia32.h ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698