| 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 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 } | 230 } |
| 231 | 231 |
| 232 private: | 232 private: |
| 233 GrowableArray<const Class*> classes_; | 233 GrowableArray<const Class*> classes_; |
| 234 GrowableArray<const LocalVariable*> locals_; | 234 GrowableArray<const LocalVariable*> locals_; |
| 235 | 235 |
| 236 DISALLOW_COPY_AND_ASSIGN(ClassesForLocals); | 236 DISALLOW_COPY_AND_ASSIGN(ClassesForLocals); |
| 237 }; | 237 }; |
| 238 | 238 |
| 239 | 239 |
| 240 static const char* kGrowableArrayClassName = "GrowableObjectArray"; | |
| 241 static const char* kGrowableArrayLengthFieldName = "_length"; | |
| 242 static const char* kGrowableArrayArrayFieldName = "backingArray"; | |
| 243 | |
| 244 | |
| 245 OptimizingCodeGenerator::OptimizingCodeGenerator( | 240 OptimizingCodeGenerator::OptimizingCodeGenerator( |
| 246 Assembler* assembler, const ParsedFunction& parsed_function) | 241 Assembler* assembler, const ParsedFunction& parsed_function) |
| 247 : CodeGenerator(assembler, parsed_function), | 242 : CodeGenerator(assembler, parsed_function), |
| 248 deoptimization_blobs_(4), | 243 deoptimization_blobs_(4), |
| 249 classes_for_locals_(new ClassesForLocals()), | 244 classes_for_locals_(new ClassesForLocals()), |
| 250 smi_class_(Class::ZoneHandle(Isolate::Current()->object_store() | 245 smi_class_(Class::ZoneHandle(Isolate::Current()->object_store() |
| 251 ->smi_class())), | 246 ->smi_class())), |
| 252 double_class_(Class::ZoneHandle(Isolate::Current()->object_store() | 247 double_class_(Class::ZoneHandle(Isolate::Current()->object_store() |
| 253 ->double_class())) { | 248 ->double_class())), |
| 249 growable_object_array_class_(Class::ZoneHandle(Isolate::Current() |
| 250 ->object_store()->growable_object_array_class())) { |
| 254 ASSERT(parsed_function.function().is_optimizable()); | 251 ASSERT(parsed_function.function().is_optimizable()); |
| 255 } | 252 } |
| 256 | 253 |
| 257 | 254 |
| 258 DeoptimizationBlob* | 255 DeoptimizationBlob* |
| 259 OptimizingCodeGenerator::AddDeoptimizationBlob(AstNode* node, | 256 OptimizingCodeGenerator::AddDeoptimizationBlob(AstNode* node, |
| 260 DeoptReasonId reason_id) { | 257 DeoptReasonId reason_id) { |
| 261 DeoptimizationBlob* d = new DeoptimizationBlob(node, reason_id); | 258 DeoptimizationBlob* d = new DeoptimizationBlob(node, reason_id); |
| 262 deoptimization_blobs_.Add(d); | 259 deoptimization_blobs_.Add(d); |
| 263 return d; | 260 return d; |
| (...skipping 1353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1617 | 1614 |
| 1618 Recognizer::Kind recognized_kind = Recognizer::RecognizeKind(target); | 1615 Recognizer::Kind recognized_kind = Recognizer::RecognizeKind(target); |
| 1619 switch (recognized_kind) { | 1616 switch (recognized_kind) { |
| 1620 case Recognizer::kObjectArrayLength: { | 1617 case Recognizer::kObjectArrayLength: { |
| 1621 TraceOpt(node, "Inlines ObjectArray.length"); | 1618 TraceOpt(node, "Inlines ObjectArray.length"); |
| 1622 __ movl(EAX, FieldAddress(EBX, Array::length_offset())); | 1619 __ movl(EAX, FieldAddress(EBX, Array::length_offset())); |
| 1623 return; | 1620 return; |
| 1624 } | 1621 } |
| 1625 case Recognizer::kGrowableArrayLength: { | 1622 case Recognizer::kGrowableArrayLength: { |
| 1626 TraceOpt(node, "Inlines GrowableObjectArray.length"); | 1623 TraceOpt(node, "Inlines GrowableObjectArray.length"); |
| 1627 intptr_t field_offset = GetFieldOffset( | 1624 __ movl(EAX, FieldAddress(EBX, GrowableObjectArray::length_offset())); |
| 1628 cls, | |
| 1629 String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName))); | |
| 1630 __ movl(EAX, FieldAddress(EBX, field_offset)); | |
| 1631 return; | 1625 return; |
| 1632 } | 1626 } |
| 1633 case Recognizer::kStringBaseLength: { | 1627 case Recognizer::kStringBaseLength: { |
| 1634 TraceOpt(node, "Inlines StringBase.length"); | 1628 TraceOpt(node, "Inlines StringBase.length"); |
| 1635 __ movl(EAX, FieldAddress(EBX, String::length_offset())); | 1629 __ movl(EAX, FieldAddress(EBX, String::length_offset())); |
| 1636 return; | 1630 return; |
| 1637 } | 1631 } |
| 1638 default: | 1632 default: |
| 1639 UNIMPLEMENTED(); | 1633 UNIMPLEMENTED(); |
| 1640 } | 1634 } |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2368 __ cmpl(EDX, FieldAddress(EBX, Array::length_offset())); | 2362 __ cmpl(EDX, FieldAddress(EBX, Array::length_offset())); |
| 2369 __ j(ABOVE_EQUAL, deopt_blob->label()); | 2363 __ j(ABOVE_EQUAL, deopt_blob->label()); |
| 2370 // Note that EDX is Smi, i.e, times 2. | 2364 // Note that EDX is Smi, i.e, times 2. |
| 2371 ASSERT(kSmiTagShift == 1); | 2365 ASSERT(kSmiTagShift == 1); |
| 2372 __ movl(EAX, FieldAddress(EBX, EDX, TIMES_2, sizeof(RawArray))); | 2366 __ movl(EAX, FieldAddress(EBX, EDX, TIMES_2, sizeof(RawArray))); |
| 2373 HandleResult(node, EAX); | 2367 HandleResult(node, EAX); |
| 2374 TraceOpt(node, kMessage); | 2368 TraceOpt(node, kMessage); |
| 2375 return; | 2369 return; |
| 2376 } | 2370 } |
| 2377 | 2371 |
| 2378 const String& growable_object_array_class_name = String::Handle( | 2372 if (AtIdNodeHasClassAt(node, node->id(), growable_object_array_class_, 0)) { |
| 2379 String::NewSymbol(kGrowableArrayClassName)); | |
| 2380 const Class& growable_array_class = Class::ZoneHandle( | |
| 2381 Library::Handle(Library::CoreImplLibrary()). | |
| 2382 LookupClass(growable_object_array_class_name)); | |
| 2383 ASSERT(!growable_array_class.IsNull()); | |
| 2384 if (AtIdNodeHasClassAt(node, node->id(), growable_array_class, 0)) { | |
| 2385 const String& growable_array_length_field_name = | |
| 2386 String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName)); | |
| 2387 const String& growable_array_array_field_name = | |
| 2388 String::Handle(String::NewSymbol(kGrowableArrayArrayFieldName)); | |
| 2389 intptr_t length_offset = GetFieldOffset(growable_array_class, | |
| 2390 growable_array_length_field_name); | |
| 2391 intptr_t array_offset = GetFieldOffset(growable_array_class, | |
| 2392 growable_array_array_field_name); | |
| 2393 CodeGenInfo array_info(node->array()); | 2373 CodeGenInfo array_info(node->array()); |
| 2394 CodeGenInfo index_info(node->index_expr()); | 2374 CodeGenInfo index_info(node->index_expr()); |
| 2395 VisitLoadTwo(node->array(), node->index_expr(), EDX, EAX); | 2375 VisitLoadTwo(node->array(), node->index_expr(), EDX, EAX); |
| 2396 DeoptimizationBlob* deopt_blob = | 2376 DeoptimizationBlob* deopt_blob = |
| 2397 AddDeoptimizationBlob(node, EDX, EAX, kDeoptLoadIndexedGrowableArray); | 2377 AddDeoptimizationBlob(node, EDX, EAX, kDeoptLoadIndexedGrowableArray); |
| 2398 // EAX: index, EDX: array. | 2378 // EAX: index, EDX: array. |
| 2399 if (!index_info.IsClass(smi_class_)) { | 2379 if (!index_info.IsClass(smi_class_)) { |
| 2400 __ testl(EAX, Immediate(kSmiTagMask)); | 2380 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2401 __ j(NOT_ZERO, deopt_blob->label()); // Not Smi index. | 2381 __ j(NOT_ZERO, deopt_blob->label()); // Not Smi index. |
| 2402 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2382 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2403 } | 2383 } |
| 2404 if (!array_info.IsClass(growable_array_class)) { | 2384 if (!array_info.IsClass(growable_object_array_class_)) { |
| 2405 __ testl(EDX, Immediate(kSmiTagMask)); | 2385 __ testl(EDX, Immediate(kSmiTagMask)); |
| 2406 __ j(ZERO, deopt_blob->label()); // Array is Smi. | 2386 __ j(ZERO, deopt_blob->label()); // Array is Smi. |
| 2407 __ movl(EBX, FieldAddress(EDX, Object::class_offset())); | 2387 __ movl(EBX, FieldAddress(EDX, Object::class_offset())); |
| 2408 __ CompareObject(EBX, growable_array_class); | 2388 __ CompareObject(EBX, growable_object_array_class_); |
| 2409 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. | 2389 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. |
| 2410 PropagateBackLocalClass(node->array(), growable_array_class); | 2390 PropagateBackLocalClass(node->array(), growable_object_array_class_); |
| 2411 } | 2391 } |
| 2412 // Range check: deoptimize if out of bounds. | 2392 // Range check: deoptimize if out of bounds. |
| 2413 __ cmpl(EAX, FieldAddress(EDX, length_offset)); | 2393 __ cmpl(EAX, FieldAddress(EDX, GrowableObjectArray::length_offset())); |
| 2414 __ j(ABOVE_EQUAL, deopt_blob->label()); | 2394 __ j(ABOVE_EQUAL, deopt_blob->label()); |
| 2415 __ movl(EDX, FieldAddress(EDX, array_offset)); // backingArray. | 2395 __ movl(EDX, FieldAddress(EDX, GrowableObjectArray::data_offset())); |
| 2416 // Note that EAX is Smi, i.e, times 2. | 2396 // Note that EAX is Smi, i.e, times 2. |
| 2417 ASSERT(kSmiTagShift == 1); | 2397 ASSERT(kSmiTagShift == 1); |
| 2418 __ movl(EAX, FieldAddress(EDX, EAX, TIMES_2, sizeof(RawArray))); | 2398 __ movl(EAX, FieldAddress(EDX, EAX, TIMES_2, sizeof(RawArray))); |
| 2419 HandleResult(node, EAX); | 2399 HandleResult(node, EAX); |
| 2420 return; | 2400 return; |
| 2421 } else { | 2401 } else { |
| 2422 // E.g., HashMap. | 2402 // E.g., HashMap. |
| 2423 TraceNotOpt(node, kMessage); | 2403 TraceNotOpt(node, kMessage); |
| 2424 } | 2404 } |
| 2425 CodeGenerator::VisitLoadIndexedNode(node); | 2405 CodeGenerator::VisitLoadIndexedNode(node); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2487 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); | 2467 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); |
| 2488 __ j(ABOVE_EQUAL, deopt_blob->label()); // Range error -> deopt. | 2468 __ j(ABOVE_EQUAL, deopt_blob->label()); // Range error -> deopt. |
| 2489 ASSERT(kSmiTagShift == 1); | 2469 ASSERT(kSmiTagShift == 1); |
| 2490 __ StoreIntoObject(EAX, | 2470 __ StoreIntoObject(EAX, |
| 2491 FieldAddress(EAX, EBX, TIMES_2, sizeof(RawArray)), | 2471 FieldAddress(EAX, EBX, TIMES_2, sizeof(RawArray)), |
| 2492 ECX); | 2472 ECX); |
| 2493 HandleResult(node, ECX); | 2473 HandleResult(node, ECX); |
| 2494 return; | 2474 return; |
| 2495 } | 2475 } |
| 2496 | 2476 |
| 2497 const String& growable_object_array_class_name = String::Handle( | 2477 if (AtIdNodeHasClassAt(node, node->id(), growable_object_array_class_, 0)) { |
| 2498 String::NewSymbol(kGrowableArrayClassName)); | |
| 2499 const Class& growable_array_class = Class::ZoneHandle( | |
| 2500 Library::Handle(Library::CoreImplLibrary()). | |
| 2501 LookupClass(growable_object_array_class_name)); | |
| 2502 ASSERT(!growable_array_class.IsNull()); | |
| 2503 if (AtIdNodeHasClassAt(node, node->id(), growable_array_class, 0)) { | |
| 2504 const String& growable_array_length_field_name = | |
| 2505 String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName)); | |
| 2506 const String& growable_array_array_field_name = | |
| 2507 String::Handle(String::NewSymbol(kGrowableArrayArrayFieldName)); | |
| 2508 intptr_t length_offset = GetFieldOffset(growable_array_class, | |
| 2509 growable_array_length_field_name); | |
| 2510 intptr_t array_offset = GetFieldOffset(growable_array_class, | |
| 2511 growable_array_array_field_name); | |
| 2512 bool index_is_smi = false; | 2478 bool index_is_smi = false; |
| 2513 // Release CodeGenInfo of index quickly as it may be used in the value, | 2479 // Release CodeGenInfo of index quickly as it may be used in the value, |
| 2514 // e.g. a[i] += 3. Fixes issue 1570. | 2480 // e.g. a[i] += 3. Fixes issue 1570. |
| 2515 { | 2481 { |
| 2516 CodeGenInfo index_info(node->index_expr()); | 2482 CodeGenInfo index_info(node->index_expr()); |
| 2517 node->index_expr()->Visit(this); | 2483 node->index_expr()->Visit(this); |
| 2518 index_is_smi = index_info.IsClass(smi_class_); | 2484 index_is_smi = index_info.IsClass(smi_class_); |
| 2519 } | 2485 } |
| 2520 VisitLoadOne(node->value(), ECX); | 2486 VisitLoadOne(node->value(), ECX); |
| 2521 DeoptimizationBlob* deopt_blob = | 2487 DeoptimizationBlob* deopt_blob = |
| 2522 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); | 2488 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); |
| 2523 __ popl(EBX); // index. | 2489 __ popl(EBX); // index. |
| 2524 __ popl(EAX); // array. | 2490 __ popl(EAX); // array. |
| 2525 // ECX: value, EBX:index, EAX: array, EDX: scratch. | 2491 // ECX: value, EBX:index, EAX: array, EDX: scratch. |
| 2526 // Check class of array. | 2492 // Check class of array. |
| 2527 if (class_of_this_array.raw() != growable_array_class.raw()) { | 2493 if (class_of_this_array.raw() != growable_object_array_class_.raw()) { |
| 2528 __ testl(EAX, Immediate(kSmiTagMask)); | 2494 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2529 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. | 2495 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. |
| 2530 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); | 2496 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); |
| 2531 __ CompareObject(EDX, growable_array_class); | 2497 __ CompareObject(EDX, growable_object_array_class_); |
| 2532 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. | 2498 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray. |
| 2533 PropagateBackLocalClass(node->array(), growable_array_class); | 2499 PropagateBackLocalClass(node->array(), growable_object_array_class_); |
| 2534 } | 2500 } |
| 2535 // Check class of index. | 2501 // Check class of index. |
| 2536 if (!index_is_smi) { | 2502 if (!index_is_smi) { |
| 2537 __ testl(EBX, Immediate(kSmiTagMask)); | 2503 __ testl(EBX, Immediate(kSmiTagMask)); |
| 2538 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. | 2504 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. |
| 2539 PropagateBackLocalClass(node->index_expr(), smi_class_); | 2505 PropagateBackLocalClass(node->index_expr(), smi_class_); |
| 2540 } | 2506 } |
| 2541 // Range check: deoptimize if out of bounds. | 2507 // Range check: deoptimize if out of bounds. |
| 2542 __ cmpl(EBX, FieldAddress(EAX, length_offset)); | 2508 __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); |
| 2543 __ j(ABOVE_EQUAL, deopt_blob->label()); | 2509 __ j(ABOVE_EQUAL, deopt_blob->label()); |
| 2544 __ movl(EDX, FieldAddress(EAX, array_offset)); // backingArray. | 2510 __ movl(EDX, FieldAddress(EAX, GrowableObjectArray::data_offset())); |
| 2545 // Note that EAX is Smi, i.e, times 2. | 2511 // Note that EAX is Smi, i.e, times 2. |
| 2546 ASSERT(kSmiTagShift == 1); | 2512 ASSERT(kSmiTagShift == 1); |
| 2547 __ StoreIntoObject(EDX, | 2513 __ StoreIntoObject(EDX, |
| 2548 FieldAddress(EDX, EBX, TIMES_2, sizeof(RawArray)), | 2514 FieldAddress(EDX, EBX, TIMES_2, sizeof(RawArray)), |
| 2549 ECX); | 2515 ECX); |
| 2550 HandleResult(node, ECX); | 2516 HandleResult(node, ECX); |
| 2551 return; | 2517 return; |
| 2552 } | 2518 } |
| 2553 node->index_expr()->Visit(this); | 2519 node->index_expr()->Visit(this); |
| 2554 node->value()->Visit(this); | 2520 node->value()->Visit(this); |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3100 } | 3066 } |
| 3101 } | 3067 } |
| 3102 // TODO(srdjan): Implement unary kSUB (negate) Mint. | 3068 // TODO(srdjan): Implement unary kSUB (negate) Mint. |
| 3103 CodeGenerator::VisitUnaryOpNode(node); | 3069 CodeGenerator::VisitUnaryOpNode(node); |
| 3104 } | 3070 } |
| 3105 | 3071 |
| 3106 | 3072 |
| 3107 } // namespace dart | 3073 } // namespace dart |
| 3108 | 3074 |
| 3109 #endif // defined TARGET_ARCH_IA32 | 3075 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |