Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/opt_code_generator.h" | 8 #include "vm/opt_code_generator.h" |
| 9 | 9 |
| 10 #include "vm/assembler_macros.h" | 10 #include "vm/assembler_macros.h" |
| (...skipping 2465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2476 } | 2476 } |
| 2477 CodeGenerator::VisitLoadIndexedNode(node); | 2477 CodeGenerator::VisitLoadIndexedNode(node); |
| 2478 } | 2478 } |
| 2479 | 2479 |
| 2480 | 2480 |
| 2481 void OptimizingCodeGenerator::VisitStoreIndexedNode(StoreIndexedNode* node) { | 2481 void OptimizingCodeGenerator::VisitStoreIndexedNode(StoreIndexedNode* node) { |
| 2482 if (FLAG_enable_type_checks) { | 2482 if (FLAG_enable_type_checks) { |
| 2483 CodeGenerator::VisitStoreIndexedNode(node); | 2483 CodeGenerator::VisitStoreIndexedNode(node); |
| 2484 return; | 2484 return; |
| 2485 } | 2485 } |
| 2486 node->array()->Visit(this); | 2486 Class& known_array_class = Class::Handle(); |
| 2487 // Load array and release its CodeGenInfo as value may refer to the same | |
| 2488 // array (e.g. in a[x] += 3). Fixes issue 1570. | |
| 2489 { | |
| 2490 CodeGenInfo array_info(node->array()); | |
| 2491 node->array()->Visit(this); | |
| 2492 known_array_class = array_info.is_class()->raw(); | |
|
hausner
2012/02/09 21:51:48
Not sure why you call this the "known" array class
srdjan
2012/02/10 07:13:11
Changing it to class_of_this_array to avoid confus
| |
| 2493 } | |
| 2487 // TODO(srdjan): Use VisitLoadTwo and check if index is smi (CodeGenInfo). | 2494 // TODO(srdjan): Use VisitLoadTwo and check if index is smi (CodeGenInfo). |
| 2488 ObjectStore* object_store = Isolate::Current()->object_store(); | 2495 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 2489 const Class& object_array_class = | 2496 const Class& object_array_class = |
| 2490 Class::ZoneHandle(object_store->array_class()); | 2497 Class::ZoneHandle(object_store->array_class()); |
| 2491 const ICData& ic_data = node->ICDataAtId(node->id()); | 2498 const ICData& ic_data = node->ICDataAtId(node->id()); |
| 2492 if (ic_data.NumberOfChecks() == 0) { | 2499 if (ic_data.NumberOfChecks() == 0) { |
| 2493 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); | 2500 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); |
| 2494 DeoptimizationBlob* deopt_blob = | 2501 DeoptimizationBlob* deopt_blob = |
| 2495 AddDeoptimizationBlob(node, EBX, ECX, kDeoptNoTypeFeedback); | 2502 AddDeoptimizationBlob(node, EBX, ECX, kDeoptNoTypeFeedback); |
| 2496 __ jmp(deopt_blob->label()); | 2503 __ jmp(deopt_blob->label()); |
| 2497 return; | 2504 return; |
| 2498 } | 2505 } |
| 2499 | 2506 |
| 2500 CodeGenInfo array_info(node->array()); | |
| 2501 CodeGenInfo index_info(node->index_expr()); | |
| 2502 | 2507 |
| 2503 if (AtIdNodeHasClassAt(node, node->id(), object_array_class, 0)) { | 2508 if (AtIdNodeHasClassAt(node, node->id(), object_array_class, 0)) { |
| 2504 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); | 2509 // Release CodeGenInfo of index quickly as it may be used in the value, |
| 2510 // e.g. a[i] += 3. Fixes issue 1570. | |
| 2511 bool index_is_smi = false; | |
| 2512 { | |
| 2513 CodeGenInfo index_info(node->index_expr()); | |
| 2514 node->index_expr()->Visit(this); | |
| 2515 index_is_smi = index_info.IsClass(smi_class_); | |
| 2516 } | |
| 2517 VisitLoadOne(node->value(), ECX); | |
| 2505 DeoptimizationBlob* deopt_blob = | 2518 DeoptimizationBlob* deopt_blob = |
| 2506 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); | 2519 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); |
| 2520 __ popl(EBX); // index. | |
| 2507 __ popl(EAX); // array. | 2521 __ popl(EAX); // array. |
| 2508 // ECX: value, EBX:index, EAX: array. | 2522 // ECX: value, EBX:index, EAX: array. |
| 2509 // Check class of array. | 2523 // Check class of array. |
| 2510 if (!array_info.IsClass(object_array_class)) { | 2524 if (known_array_class.raw() != object_array_class.raw()) { |
| 2511 __ testl(EAX, Immediate(kSmiTagMask)); | 2525 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2512 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. | 2526 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. |
| 2513 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); | 2527 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); |
| 2514 __ CompareObject(EDX, object_array_class); | 2528 __ CompareObject(EDX, object_array_class); |
| 2515 __ j(NOT_EQUAL, deopt_blob->label()); // Not ObjectArray -> deopt. | 2529 __ j(NOT_EQUAL, deopt_blob->label()); // Not ObjectArray -> deopt. |
| 2516 PropagateBackLocalClass(node->array(), object_array_class); | 2530 PropagateBackLocalClass(node->array(), object_array_class); |
| 2517 } | 2531 } |
| 2518 // Check class of index. | 2532 // Check class of index. |
| 2519 if (!index_info.IsClass(smi_class_)) { | 2533 if (!index_is_smi) { |
| 2520 __ testl(EBX, Immediate(kSmiTagMask)); | 2534 __ testl(EBX, Immediate(kSmiTagMask)); |
| 2521 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. | 2535 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. |
| 2522 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2536 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2523 } | 2537 } |
| 2524 // Range check. | 2538 // Range check. |
| 2525 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); | 2539 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); |
| 2526 __ j(ABOVE_EQUAL, deopt_blob->label()); // Range error -> deopt. | 2540 __ j(ABOVE_EQUAL, deopt_blob->label()); // Range error -> deopt. |
| 2527 ASSERT(kSmiTagShift == 1); | 2541 ASSERT(kSmiTagShift == 1); |
| 2528 __ StoreIntoObject(EAX, | 2542 __ StoreIntoObject(EAX, |
| 2529 FieldAddress(EAX, EBX, TIMES_2, sizeof(RawArray)), | 2543 FieldAddress(EAX, EBX, TIMES_2, sizeof(RawArray)), |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 2540 ASSERT(!growable_array_class.IsNull()); | 2554 ASSERT(!growable_array_class.IsNull()); |
| 2541 if (AtIdNodeHasClassAt(node, node->id(), growable_array_class, 0)) { | 2555 if (AtIdNodeHasClassAt(node, node->id(), growable_array_class, 0)) { |
| 2542 const String& growable_array_length_field_name = | 2556 const String& growable_array_length_field_name = |
| 2543 String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName)); | 2557 String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName)); |
| 2544 const String& growable_array_array_field_name = | 2558 const String& growable_array_array_field_name = |
| 2545 String::Handle(String::NewSymbol(kGrowableArrayArrayFieldName)); | 2559 String::Handle(String::NewSymbol(kGrowableArrayArrayFieldName)); |
| 2546 intptr_t length_offset = GetFieldOffset(growable_array_class, | 2560 intptr_t length_offset = GetFieldOffset(growable_array_class, |
| 2547 growable_array_length_field_name); | 2561 growable_array_length_field_name); |
| 2548 intptr_t array_offset = GetFieldOffset(growable_array_class, | 2562 intptr_t array_offset = GetFieldOffset(growable_array_class, |
| 2549 growable_array_array_field_name); | 2563 growable_array_array_field_name); |
| 2550 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); | 2564 bool index_is_smi = false; |
| 2565 // Release CodeGenInfo of index quickly as it may be used in the value, | |
| 2566 // e.g. a[i] += 3. Fixes issue 1570. | |
| 2567 { | |
| 2568 CodeGenInfo index_info(node->index_expr()); | |
| 2569 node->index_expr()->Visit(this); | |
| 2570 index_is_smi = index_info.IsClass(smi_class_); | |
| 2571 } | |
| 2572 VisitLoadOne(node->value(), ECX); | |
| 2551 DeoptimizationBlob* deopt_blob = | 2573 DeoptimizationBlob* deopt_blob = |
| 2552 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); | 2574 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); |
| 2553 __ popl(EAX); // Array. | 2575 __ popl(EBX); // index. |
| 2576 __ popl(EAX); // array. | |
| 2554 // ECX: value, EBX:index, EAX: array, EDX: scratch. | 2577 // ECX: value, EBX:index, EAX: array, EDX: scratch. |
| 2555 // Check class of array. | 2578 // Check class of array. |
| 2556 if (!array_info.IsClass(growable_array_class)) { | 2579 if (known_array_class.raw() != growable_array_class.raw()) { |
| 2557 __ testl(EAX, Immediate(kSmiTagMask)); | 2580 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2558 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. | 2581 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. |
| 2559 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); | 2582 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); |
| 2560 __ CompareObject(EDX, growable_array_class); | 2583 __ CompareObject(EDX, growable_array_class); |
| 2561 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. | 2584 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. |
| 2562 PropagateBackLocalClass(node->array(), growable_array_class); | 2585 PropagateBackLocalClass(node->array(), growable_array_class); |
| 2563 } | 2586 } |
| 2564 // Check class of index. | 2587 // Check class of index. |
| 2565 if (!index_info.IsClass(smi_class_)) { | 2588 if (!index_is_smi) { |
| 2566 __ testl(EBX, Immediate(kSmiTagMask)); | 2589 __ testl(EBX, Immediate(kSmiTagMask)); |
| 2567 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. | 2590 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. |
| 2568 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2591 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2569 } | 2592 } |
| 2570 // Range check: deoptimize if out of bounds. | 2593 // Range check: deoptimize if out of bounds. |
| 2571 __ cmpl(EBX, FieldAddress(EAX, length_offset)); | 2594 __ cmpl(EBX, FieldAddress(EAX, length_offset)); |
| 2572 __ j(ABOVE_EQUAL, deopt_blob->label()); | 2595 __ j(ABOVE_EQUAL, deopt_blob->label()); |
| 2573 __ movl(EDX, FieldAddress(EAX, array_offset)); // backingArray. | 2596 __ movl(EDX, FieldAddress(EAX, array_offset)); // backingArray. |
| 2574 // Note that EAX is Smi, i.e, times 2. | 2597 // Note that EAX is Smi, i.e, times 2. |
| 2575 ASSERT(kSmiTagShift == 1); | 2598 ASSERT(kSmiTagShift == 1); |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3123 } | 3146 } |
| 3124 } | 3147 } |
| 3125 // TODO(srdjan): Implement unary kSUB (negate) Mint. | 3148 // TODO(srdjan): Implement unary kSUB (negate) Mint. |
| 3126 CodeGenerator::VisitUnaryOpNode(node); | 3149 CodeGenerator::VisitUnaryOpNode(node); |
| 3127 } | 3150 } |
| 3128 | 3151 |
| 3129 | 3152 |
| 3130 } // namespace dart | 3153 } // namespace dart |
| 3131 | 3154 |
| 3132 #endif // defined TARGET_ARCH_IA32 | 3155 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |