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

Side by Side Diff: runtime/vm/flow_graph_compiler_x64.cc

Issue 9665029: Generate code for instance of: copy from CodeGenerator. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "vm/ast_printer.h" 10 #include "vm/ast_printer.h"
11 #include "vm/code_generator.h" 11 #include "vm/code_generator.h"
12 #include "vm/disassembler.h" 12 #include "vm/disassembler.h"
13 #include "vm/longjump.h" 13 #include "vm/longjump.h"
14 #include "vm/object_store.h"
14 #include "vm/parser.h" 15 #include "vm/parser.h"
15 #include "vm/stub_code.h" 16 #include "vm/stub_code.h"
16 17
17 namespace dart { 18 namespace dart {
18 19
19 DECLARE_FLAG(bool, print_ast); 20 DECLARE_FLAG(bool, print_ast);
20 DECLARE_FLAG(bool, print_scopes); 21 DECLARE_FLAG(bool, print_scopes);
21 DECLARE_FLAG(bool, trace_functions); 22 DECLARE_FLAG(bool, trace_functions);
22 23
23 FlowGraphCompiler::FlowGraphCompiler( 24 FlowGraphCompiler::FlowGraphCompiler(
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 Label done; 321 Label done;
321 LoadValue(RDX, comp->value()); 322 LoadValue(RDX, comp->value());
322 __ LoadObject(RAX, bool_true); 323 __ LoadObject(RAX, bool_true);
323 __ cmpq(RAX, RDX); 324 __ cmpq(RAX, RDX);
324 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 325 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
325 __ LoadObject(RAX, bool_false); 326 __ LoadObject(RAX, bool_false);
326 __ Bind(&done); 327 __ Bind(&done);
327 } 328 }
328 329
329 330
331 static const Class* CoreClass(const char* c_name) {
332 const String& class_name = String::Handle(String::NewSymbol(c_name));
333 const Class& cls = Class::ZoneHandle(Library::Handle(
334 Library::CoreImplLibrary()).LookupClass(class_name));
335 ASSERT(!cls.IsNull());
336 return &cls;
337 }
338
339
340 void FlowGraphCompiler::GenerateInstantiatorTypeArguments(
341 intptr_t token_index) {
342 Bailout("FlowGraphCompiler::GenerateInstantiatorTypeArguments");
343 }
344
345
346 // Copied from CodeGenerator.
347 // Optimize instanceof type test by adding inlined tests for:
348 // - NULL -> return false.
349 // - Smi -> compile time subtype check (only if dst class is not parameterized).
350 // - Class equality (only if class is not parameterized).
351 // Inputs:
352 // - RAX: object.
353 // Destroys RCX.
354 // Returns:
355 // - true or false in RAX.
356 void FlowGraphCompiler::GenerateInstanceOf(intptr_t node_id,
357 intptr_t token_index,
358 const AbstractType& type,
359 bool negate_result) {
360 ASSERT(type.IsFinalized() && !type.IsMalformed());
361 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
362 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
363
364 // All instances are of a subtype of the Object type.
365 const Type& object_type =
366 Type::Handle(Isolate::Current()->object_store()->object_type());
367 Error& malformed_error = Error::Handle();
368 if (type.IsInstantiated() &&
369 object_type.IsSubtypeOf(type, &malformed_error)) {
370 __ LoadObject(RAX, negate_result ? bool_false : bool_true);
371 return;
372 }
373
374 const Immediate raw_null =
375 Immediate(reinterpret_cast<intptr_t>(Object::null()));
376 Label done;
377 // If type is instantiated and non-parameterized, we can inline code
378 // checking whether the tested instance is a Smi.
379 if (type.IsInstantiated()) {
380 // A null object is only an instance of Object and Dynamic, which has
381 // already been checked above (if the type is instantiated). So we can
382 // return false here if the instance is null (and if the type is
383 // instantiated).
384 // We can only inline this null check if the type is instantiated at compile
385 // time, since an uninstantiated type at compile time could be Object or
386 // Dynamic at run time.
387 Label non_null;
388 __ cmpq(RAX, raw_null);
389 __ j(NOT_EQUAL, &non_null, Assembler::kNearJump);
390 __ PushObject(negate_result ? bool_true : bool_false);
391 __ jmp(&done);
392
393 __ Bind(&non_null);
394
395 const Class& type_class = Class::ZoneHandle(type.type_class());
396 const bool requires_type_arguments = type_class.HasTypeArguments();
397 // A Smi object cannot be the instance of a parameterized class.
398 // A class equality check is only applicable with a dst type of a
399 // non-parameterized class or with a raw dst type of a parameterized class.
400 if (requires_type_arguments) {
401 const AbstractTypeArguments& type_arguments =
402 AbstractTypeArguments::Handle(type.arguments());
403 const bool is_raw_type = type_arguments.IsNull() ||
404 type_arguments.IsDynamicTypes(type_arguments.Length());
405 Label runtime_call;
406 __ testq(RAX, Immediate(kSmiTagMask));
407 __ j(ZERO, &runtime_call, Assembler::kNearJump);
408 // Object not Smi.
409 if (is_raw_type) {
410 if (type.IsListInterface()) {
411 Label push_result;
412 // TODO(srdjan) also accept List<Object>.
413 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
414 __ CompareObject(RCX, *CoreClass("ObjectArray"));
415 __ j(EQUAL, &push_result, Assembler::kNearJump);
416 __ CompareObject(RCX, *CoreClass("GrowableObjectArray"));
417 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump);
418 __ Bind(&push_result);
419 __ PushObject(negate_result ? bool_false : bool_true);
420 __ jmp(&done);
421 } else if (!type_class.is_interface()) {
422 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
423 __ CompareObject(RCX, type_class);
424 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump);
425 __ PushObject(negate_result ? bool_false : bool_true);
426 __ jmp(&done);
427 }
428 }
429 __ Bind(&runtime_call);
430 // Fall through to runtime call.
431 } else {
432 Label compare_classes;
433 __ testq(RAX, Immediate(kSmiTagMask));
434 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
435 // Object is Smi.
436 const Class& smi_class = Class::Handle(Smi::Class());
437 // TODO(regis): We should introduce a SmiType.
438 Error& malformed_error = Error::Handle();
439 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
440 type_class,
441 TypeArguments::Handle(),
442 &malformed_error)) {
443 __ PushObject(negate_result ? bool_false : bool_true);
444 } else {
445 __ PushObject(negate_result ? bool_true : bool_false);
446 }
447 __ jmp(&done);
448
449 // Compare if the classes are equal.
450 __ Bind(&compare_classes);
451 const Class* compare_class = NULL;
452 if (type.IsStringInterface()) {
453 compare_class = &Class::ZoneHandle(
454 Isolate::Current()->object_store()->one_byte_string_class());
455 } else if (type.IsBoolInterface()) {
456 compare_class = &Class::ZoneHandle(
457 Isolate::Current()->object_store()->bool_class());
458 } else if (!type_class.is_interface()) {
459 compare_class = &type_class;
460 }
461 if (compare_class != NULL) {
462 Label runtime_call;
463 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
464 __ CompareObject(RCX, *compare_class);
465 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump);
466 __ PushObject(negate_result ? bool_false : bool_true);
467 __ jmp(&done, Assembler::kNearJump);
468 __ Bind(&runtime_call);
469 }
470 }
471 }
472 __ PushObject(Object::ZoneHandle()); // Make room for the result.
473 const Immediate location =
474 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index)));
475 __ pushq(location); // Push the source location.
476 __ pushq(RAX); // Push the instance.
477 __ PushObject(type); // Push the type.
478 if (!type.IsInstantiated()) {
479 GenerateInstantiatorTypeArguments(token_index);
480 } else {
481 __ pushq(raw_null); // Null instantiator.
482 }
483 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry);
484 // Pop the two parameters supplied to the runtime entry. The result of the
485 // instanceof runtime call will be left as the result of the operation.
486 __ addq(RSP, Immediate(4 * kWordSize));
487 if (negate_result) {
488 Label negate_done;
489 __ popq(RDX);
490 __ LoadObject(RAX, bool_true);
491 __ cmpq(RDX, RAX);
492 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump);
493 __ LoadObject(RAX, bool_false);
494 __ Bind(&negate_done);
495 __ pushq(RAX);
496 }
497 __ Bind(&done);
498 __ popq(RAX);
499 }
500
501
330 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { 502 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) {
331 Bailout("InstanceOf"); 503 __ popq(RAX);
504 GenerateInstanceOf(comp->node_id(),
505 comp->token_index(),
506 comp->type(),
507 comp->negate_result());
332 } 508 }
333 509
334 510
335 void FlowGraphCompiler::VisitAllocateObject(AllocateObjectComp* comp) { 511 void FlowGraphCompiler::VisitAllocateObject(AllocateObjectComp* comp) {
336 const Class& cls = Class::ZoneHandle(comp->constructor().owner()); 512 const Class& cls = Class::ZoneHandle(comp->constructor().owner());
337 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); 513 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
338 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); 514 const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
339 GenerateCall(comp->token_index(), &label, PcDescriptors::kOther); 515 GenerateCall(comp->token_index(), &label, PcDescriptors::kOther);
340 for (intptr_t i = 0; i < comp->arguments().length(); i++) { 516 for (intptr_t i = 0; i < comp->arguments().length(); i++) {
341 __ popq(RCX); // Discard allocation argument 517 __ popq(RCX); // Discard allocation argument
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) { 808 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) {
633 // We don't compile exception handlers yet. 809 // We don't compile exception handlers yet.
634 code.set_exception_handlers( 810 code.set_exception_handlers(
635 ExceptionHandlers::Handle(ExceptionHandlers::New(0))); 811 ExceptionHandlers::Handle(ExceptionHandlers::New(0)));
636 } 812 }
637 813
638 814
639 } // namespace dart 815 } // namespace dart
640 816
641 #endif // defined TARGET_ARCH_X64 817 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698