| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3438 HValue* value = environment()->Pop(); | 3438 HValue* value = environment()->Pop(); |
| 3439 HThrow* instr = new HThrow(value); | 3439 HThrow* instr = new HThrow(value); |
| 3440 instr->set_position(expr->position()); | 3440 instr->set_position(expr->position()); |
| 3441 AddInstruction(instr); | 3441 AddInstruction(instr); |
| 3442 AddSimulate(expr->id()); | 3442 AddSimulate(expr->id()); |
| 3443 current_block()->FinishExit(new HAbnormalExit); | 3443 current_block()->FinishExit(new HAbnormalExit); |
| 3444 set_current_block(NULL); | 3444 set_current_block(NULL); |
| 3445 } | 3445 } |
| 3446 | 3446 |
| 3447 | 3447 |
| 3448 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | |
| 3449 HValue* object, | |
| 3450 ZoneMapList* types, | |
| 3451 Handle<String> name) { | |
| 3452 // TODO(ager): We should recognize when the prototype chains for different | |
| 3453 // maps are identical. In that case we can avoid repeatedly generating the | |
| 3454 // same prototype map checks. | |
| 3455 int count = 0; | |
| 3456 HBasicBlock* join = NULL; | |
| 3457 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | |
| 3458 Handle<Map> map = types->at(i); | |
| 3459 LookupResult lookup; | |
| 3460 map->LookupInDescriptors(NULL, *name, &lookup); | |
| 3461 if (lookup.IsProperty() && lookup.type() == FIELD) { | |
| 3462 if (count == 0) { | |
| 3463 AddInstruction(new HCheckNonSmi(object)); // Only needed once. | |
| 3464 join = graph()->CreateBasicBlock(); | |
| 3465 } | |
| 3466 ++count; | |
| 3467 HBasicBlock* if_true = graph()->CreateBasicBlock(); | |
| 3468 HBasicBlock* if_false = graph()->CreateBasicBlock(); | |
| 3469 HCompareMap* compare = new HCompareMap(object, map, if_true, if_false); | |
| 3470 current_block()->Finish(compare); | |
| 3471 | |
| 3472 set_current_block(if_true); | |
| 3473 HLoadNamedField* instr = | |
| 3474 BuildLoadNamedField(object, expr, map, &lookup, false); | |
| 3475 instr->set_position(expr->position()); | |
| 3476 instr->ClearFlag(HValue::kUseGVN); | |
| 3477 AddInstruction(instr); | |
| 3478 if (!ast_context()->IsEffect()) Push(instr); | |
| 3479 current_block()->Goto(join); | |
| 3480 | |
| 3481 set_current_block(if_false); | |
| 3482 } | |
| 3483 } | |
| 3484 | |
| 3485 // Finish up. Unconditionally deoptimize if we've handled all the maps we | |
| 3486 // know about and do not want to handle ones we've never seen. Otherwise | |
| 3487 // use a generic IC. | |
| 3488 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | |
| 3489 current_block()->FinishExitWithDeoptimization(); | |
| 3490 } else { | |
| 3491 HInstruction* instr = BuildLoadNamedGeneric(object, expr); | |
| 3492 instr->set_position(expr->position()); | |
| 3493 | |
| 3494 if (join != NULL) { | |
| 3495 AddInstruction(instr); | |
| 3496 if (!ast_context()->IsEffect()) Push(instr); | |
| 3497 current_block()->Goto(join); | |
| 3498 } else { | |
| 3499 ast_context()->ReturnInstruction(instr, expr->id()); | |
| 3500 return; | |
| 3501 } | |
| 3502 } | |
| 3503 | |
| 3504 ASSERT(join != NULL); | |
| 3505 join->SetJoinId(expr->id()); | |
| 3506 set_current_block(join); | |
| 3507 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | |
| 3508 } | |
| 3509 | |
| 3510 | |
| 3511 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 3448 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 3512 Property* expr, | 3449 Property* expr, |
| 3513 Handle<Map> type, | 3450 Handle<Map> type, |
| 3514 LookupResult* lookup, | 3451 LookupResult* lookup, |
| 3515 bool smi_and_map_check) { | 3452 bool smi_and_map_check) { |
| 3516 if (smi_and_map_check) { | 3453 if (smi_and_map_check) { |
| 3517 AddInstruction(new HCheckNonSmi(object)); | 3454 AddInstruction(new HCheckNonSmi(object)); |
| 3518 AddInstruction(new HCheckMap(object, type)); | 3455 AddInstruction(new HCheckMap(object, type)); |
| 3519 } | 3456 } |
| 3520 | 3457 |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3741 instr = new HLoadFunctionPrototype(function); | 3678 instr = new HLoadFunctionPrototype(function); |
| 3742 | 3679 |
| 3743 } else if (expr->key()->IsPropertyName()) { | 3680 } else if (expr->key()->IsPropertyName()) { |
| 3744 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 3681 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 3745 ZoneMapList* types = expr->GetReceiverTypes(); | 3682 ZoneMapList* types = expr->GetReceiverTypes(); |
| 3746 | 3683 |
| 3747 HValue* obj = Pop(); | 3684 HValue* obj = Pop(); |
| 3748 if (expr->IsMonomorphic()) { | 3685 if (expr->IsMonomorphic()) { |
| 3749 instr = BuildLoadNamed(obj, expr, types->first(), name); | 3686 instr = BuildLoadNamed(obj, expr, types->first(), name); |
| 3750 } else if (types != NULL && types->length() > 1) { | 3687 } else if (types != NULL && types->length() > 1) { |
| 3751 HandlePolymorphicLoadNamedField(expr, obj, types, name); | 3688 AddInstruction(new HCheckNonSmi(obj)); |
| 3752 return; | 3689 instr = new HLoadNamedFieldPolymorphic(obj, types, name); |
| 3753 | |
| 3754 } else { | 3690 } else { |
| 3755 instr = BuildLoadNamedGeneric(obj, expr); | 3691 instr = BuildLoadNamedGeneric(obj, expr); |
| 3756 } | 3692 } |
| 3757 | 3693 |
| 3758 } else { | 3694 } else { |
| 3759 VISIT_FOR_VALUE(expr->key()); | 3695 VISIT_FOR_VALUE(expr->key()); |
| 3760 | 3696 |
| 3761 HValue* key = Pop(); | 3697 HValue* key = Pop(); |
| 3762 HValue* obj = Pop(); | 3698 HValue* obj = Pop(); |
| 3763 | 3699 |
| (...skipping 2178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5942 } | 5878 } |
| 5943 } | 5879 } |
| 5944 | 5880 |
| 5945 #ifdef DEBUG | 5881 #ifdef DEBUG |
| 5946 if (graph_ != NULL) graph_->Verify(); | 5882 if (graph_ != NULL) graph_->Verify(); |
| 5947 if (allocator_ != NULL) allocator_->Verify(); | 5883 if (allocator_ != NULL) allocator_->Verify(); |
| 5948 #endif | 5884 #endif |
| 5949 } | 5885 } |
| 5950 | 5886 |
| 5951 } } // namespace v8::internal | 5887 } } // namespace v8::internal |
| OLD | NEW |