OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1448 | 1448 |
1449 // Only move instructions that postdominate the loop header (i.e. are | 1449 // Only move instructions that postdominate the loop header (i.e. are |
1450 // always executed inside the loop). This is to avoid unnecessary | 1450 // always executed inside the loop). This is to avoid unnecessary |
1451 // deoptimizations assuming the loop is executed at least once. | 1451 // deoptimizations assuming the loop is executed at least once. |
1452 // TODO(fschneider): Better type feedback should give us information | 1452 // TODO(fschneider): Better type feedback should give us information |
1453 // about code that was never executed. | 1453 // about code that was never executed. |
1454 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr, | 1454 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr, |
1455 HBasicBlock* loop_header) { | 1455 HBasicBlock* loop_header) { |
1456 if (!instr->IsChange() && | 1456 if (!instr->IsChange() && |
1457 FLAG_aggressive_loop_invariant_motion) return true; | 1457 FLAG_aggressive_loop_invariant_motion) return true; |
1458 | |
1459 // Don't hoist named loads that are part of polymorphic loads. | |
1460 if (instr->IsLoadNamedField() && | |
Kevin Millikin (Chromium)
2010/12/20 12:34:34
You could accomplish essentially the same thing by
| |
1461 HLoadNamedField::cast(instr)->is_polymorphic()) { | |
1462 return false; | |
1463 } | |
1464 | |
1458 HBasicBlock* block = instr->block(); | 1465 HBasicBlock* block = instr->block(); |
1459 bool result = true; | 1466 bool result = true; |
1460 if (block != loop_header) { | 1467 if (block != loop_header) { |
1461 for (int i = 1; i < loop_header->predecessors()->length(); ++i) { | 1468 for (int i = 1; i < loop_header->predecessors()->length(); ++i) { |
1462 bool found = false; | 1469 bool found = false; |
1463 HBasicBlock* pred = loop_header->predecessors()->at(i); | 1470 HBasicBlock* pred = loop_header->predecessors()->at(i); |
1464 while (pred != loop_header) { | 1471 while (pred != loop_header) { |
1465 if (pred == block) found = true; | 1472 if (pred == block) found = true; |
1466 pred = pred->dominator(); | 1473 pred = pred->dominator(); |
1467 } | 1474 } |
(...skipping 2057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3525 // different maps are identical. In that case we can avoid | 3532 // different maps are identical. In that case we can avoid |
3526 // repeatedly generating the same prototype map checks. | 3533 // repeatedly generating the same prototype map checks. |
3527 for (int i = 0; i < number_of_types; ++i) { | 3534 for (int i = 0; i < number_of_types; ++i) { |
3528 Handle<Map> map = types->at(i); | 3535 Handle<Map> map = types->at(i); |
3529 LookupResult lookup; | 3536 LookupResult lookup; |
3530 map->LookupInDescriptors(NULL, *name, &lookup); | 3537 map->LookupInDescriptors(NULL, *name, &lookup); |
3531 if (lookup.IsProperty() && lookup.type() == FIELD) { | 3538 if (lookup.IsProperty() && lookup.type() == FIELD) { |
3532 maps.Add(map); | 3539 maps.Add(map); |
3533 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3540 HSubgraph* subgraph = CreateBranchSubgraph(environment()); |
3534 SubgraphScope scope(this, subgraph); | 3541 SubgraphScope scope(this, subgraph); |
3535 HInstruction* instr = | 3542 HLoadNamedField* instr = |
3536 BuildLoadNamedField(object, expr, map, &lookup, false); | 3543 BuildLoadNamedField(object, expr, map, &lookup, false); |
3537 instr->set_position(expr->position()); | 3544 instr->set_position(expr->position()); |
3545 instr->set_is_polymorphic(true); | |
3538 PushAndAdd(instr); | 3546 PushAndAdd(instr); |
3539 subgraphs.Add(subgraph); | 3547 subgraphs.Add(subgraph); |
3540 } else { | 3548 } else { |
3541 needs_generic = true; | 3549 needs_generic = true; |
3542 } | 3550 } |
3543 } | 3551 } |
3544 | 3552 |
3545 // If none of the properties were named fields we generate a | 3553 // If none of the properties were named fields we generate a |
3546 // generic load. | 3554 // generic load. |
3547 if (maps.length() == 0) { | 3555 if (maps.length() == 0) { |
(...skipping 18 matching lines...) Expand all Loading... | |
3566 | 3574 |
3567 HBasicBlock* new_exit_block = | 3575 HBasicBlock* new_exit_block = |
3568 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); | 3576 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); |
3569 subgraph()->set_exit_block(new_exit_block); | 3577 subgraph()->set_exit_block(new_exit_block); |
3570 } | 3578 } |
3571 | 3579 |
3572 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop()); | 3580 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop()); |
3573 } | 3581 } |
3574 | 3582 |
3575 | 3583 |
3576 HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object, | 3584 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
3577 Property* expr, | 3585 Property* expr, |
3578 Handle<Map> type, | 3586 Handle<Map> type, |
3579 LookupResult* lookup, | 3587 LookupResult* lookup, |
3580 bool smi_and_map_check) { | 3588 bool smi_and_map_check) { |
3581 if (smi_and_map_check) { | 3589 if (smi_and_map_check) { |
3582 AddInstruction(new HCheckNonSmi(object)); | 3590 AddInstruction(new HCheckNonSmi(object)); |
3583 AddInstruction(new HCheckMap(object, type)); | 3591 AddInstruction(new HCheckMap(object, type)); |
3584 } | 3592 } |
3585 | 3593 |
3586 int index = lookup->GetLocalFieldIndexFromMap(*type); | 3594 int index = lookup->GetLocalFieldIndexFromMap(*type); |
3587 if (index < 0) { | 3595 if (index < 0) { |
3588 // Negative property indices are in-object properties, indexed | 3596 // Negative property indices are in-object properties, indexed |
3589 // from the end of the fixed part of the object. | 3597 // from the end of the fixed part of the object. |
3590 int offset = (index * kPointerSize) + type->instance_size(); | 3598 int offset = (index * kPointerSize) + type->instance_size(); |
(...skipping 2083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5674 } | 5682 } |
5675 | 5683 |
5676 #ifdef DEBUG | 5684 #ifdef DEBUG |
5677 if (graph_ != NULL) graph_->Verify(); | 5685 if (graph_ != NULL) graph_->Verify(); |
5678 if (chunk_ != NULL) chunk_->Verify(); | 5686 if (chunk_ != NULL) chunk_->Verify(); |
5679 if (allocator_ != NULL) allocator_->Verify(); | 5687 if (allocator_ != NULL) allocator_->Verify(); |
5680 #endif | 5688 #endif |
5681 } | 5689 } |
5682 | 5690 |
5683 } } // namespace v8::internal | 5691 } } // namespace v8::internal |
OLD | NEW |