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

Side by Side Diff: src/hydrogen.cc

Issue 11414201: Make HJSArrayLength more likely to have identical GVNs. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years 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 | « src/hydrogen.h ('k') | src/hydrogen-instructions.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 679 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 } 690 }
691 691
692 692
693 HGraph::HGraph(CompilationInfo* info) 693 HGraph::HGraph(CompilationInfo* info)
694 : isolate_(info->isolate()), 694 : isolate_(info->isolate()),
695 next_block_id_(0), 695 next_block_id_(0),
696 entry_block_(NULL), 696 entry_block_(NULL),
697 blocks_(8, info->zone()), 697 blocks_(8, info->zone()),
698 values_(16, info->zone()), 698 values_(16, info->zone()),
699 phi_list_(NULL), 699 phi_list_(NULL),
700 array_lengths_(8, info->zone()),
700 uint32_instructions_(NULL), 701 uint32_instructions_(NULL),
701 info_(info), 702 info_(info),
702 zone_(info->zone()), 703 zone_(info->zone()),
703 is_recursive_(false), 704 is_recursive_(false),
704 use_optimistic_licm_(false), 705 use_optimistic_licm_(false),
705 type_change_checksum_(0) { 706 type_change_checksum_(0) {
706 start_environment_ = 707 start_environment_ =
707 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); 708 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
708 start_environment_->set_ast_id(BailoutId::FunctionEntry()); 709 start_environment_->set_ast_id(BailoutId::FunctionEntry());
709 entry_block_ = CreateBasicBlock(); 710 entry_block_ = CreateBasicBlock();
710 entry_block_->SetInitialEnvironment(start_environment_); 711 entry_block_->SetInitialEnvironment(start_environment_);
711 } 712 }
712 713
713 714
714 HBasicBlock* HGraph::CreateBasicBlock() { 715 HBasicBlock* HGraph::CreateBasicBlock() {
715 HBasicBlock* result = new(zone()) HBasicBlock(this); 716 HBasicBlock* result = new(zone()) HBasicBlock(this);
716 blocks_.Add(result, zone()); 717 blocks_.Add(result, zone());
717 return result; 718 return result;
718 } 719 }
719 720
720 721
722 static int CompareJSArrayLengthsByValues(HJSArrayLength* const* x,
723 HJSArrayLength* const* y) {
724 return Compare<int>((*x)->value()->id(), (*y)->value()->id());
725 }
726
727
728 void HGraph::ProcessJSArrayLengths() {
729 HPhase phase("H_ProcessJSArrayLengths", this);
730 array_lengths_.Sort(CompareJSArrayLengthsByValues);
731
732 int group_start_index = 0;
733 while (group_start_index < array_lengths_.length()) {
734 // First, find the set of HJSArrayLength insts that operate on the same
danno 2012/11/28 12:44:31 please don't use abbreviations, "insts" should be
735 // array and see if all the ones that are guarded by a map check do a
736 // check for the same map.
737 bool map_check_can_be_shared = true;
738 HCheckMaps* map_check = NULL;
739 HType type = HType::Tagged();
740 int group_end_index = group_start_index;
741 while (group_end_index < array_lengths_.length() &&
danno 2012/11/28 12:44:31 This algorithm is a no-go. It is quadratic with r
742 array_lengths_.at(group_end_index)->value()->id() ==
743 array_lengths_.at(group_start_index)->value()->id()) {
744 HJSArrayLength* inst = array_lengths_.at(group_end_index);
745 if (inst->typecheck()->IsCheckMaps()) {
746 HCheckMaps* current_map_check = HCheckMaps::cast(inst->typecheck());
747 if (current_map_check->has_dependency()) {
748 // Element transitions would cause deopts...
749 map_check_can_be_shared = false;
750 } else {
751 if (map_check != NULL) {
752 if (current_map_check->map_set()->length() ==
753 map_check->map_set()->length()) {
754 for (int i = 0; i < map_check->map_set()->length(); i++) {
755 if (*(map_check->map_set()->at(i)) !=
756 *(current_map_check->map_set()->at(i))) {
757 map_check_can_be_shared = false;
758 break;
759 }
760
761 // Record the check higher in the dominator tree.
762 if (current_map_check->block()->Dominates(
763 map_check->block())) {
764 map_check = current_map_check;
danno 2012/11/28 12:44:31 This is not sufficient and leads to incorrect code
765 }
766 }
767 } else {
768 map_check_can_be_shared = false;
769 }
770 } else {
771 map_check = current_map_check;
772 type = inst->type();
773 }
774 }
775 } else if (!inst->typecheck()->IsCheckInstanceType()) {
776 map_check_can_be_shared = false;
777 }
778
779 group_end_index++;
780 }
781
782 // If we do have a map check and it is unique, make so that all the other
783 // HJSArrayLength instructions are guarded by the same check.
784 if (map_check != NULL && map_check_can_be_shared) {
785 for (int i = group_start_index; i < group_end_index; i++) {
786 HJSArrayLength* inst = array_lengths_.at(i);
787 if (inst->typecheck()->IsCheckInstanceType()) {
788 HValue* typecheck = inst->typecheck();
789 // For now don't handle complex cases which should not even happen.
790 if (typecheck->UseCount() == 1) {
791 // Use new_check directly if it dominates this location, otherwise
792 // create a new identical check (GVN can collapse them anyway).
793 HCheckMaps* new_check;
794 if (map_check->block()->Dominates(inst->block())) {
795 new_check = map_check;
796 } else {
797 new_check = new(zone()) HCheckMaps(
798 inst->value(), map_check->map_set(), zone());
799 new_check->InsertBefore(inst);
800 }
801 typecheck->DeleteAndReplaceWith(new_check);
802 inst->set_type(type);
803 }
804 }
805 }
806 }
807
808 // Move to next "group".
809 group_start_index = group_end_index;
810 }
811 }
812
813
721 void HGraph::Canonicalize() { 814 void HGraph::Canonicalize() {
722 if (!FLAG_use_canonicalizing) return; 815 if (!FLAG_use_canonicalizing) return;
723 HPhase phase("H_Canonicalize", this); 816 HPhase phase("H_Canonicalize", this);
724 for (int i = 0; i < blocks()->length(); ++i) { 817 for (int i = 0; i < blocks()->length(); ++i) {
725 HInstruction* instr = blocks()->at(i)->first(); 818 HInstruction* instr = blocks()->at(i)->first();
726 while (instr != NULL) { 819 while (instr != NULL) {
727 HValue* value = instr->Canonicalize(); 820 HValue* value = instr->Canonicalize();
728 if (value != instr) instr->DeleteAndReplaceWith(value); 821 if (value != instr) instr->DeleteAndReplaceWith(value);
729 instr = instr->next(); 822 instr = instr->next();
730 } 823 }
(...skipping 2564 matching lines...) Expand 10 before | Expand all | Expand 10 after
3295 3388
3296 InitializeInferredTypes(); 3389 InitializeInferredTypes();
3297 3390
3298 // Must be performed before canonicalization to ensure that Canonicalize 3391 // Must be performed before canonicalization to ensure that Canonicalize
3299 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with 3392 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
3300 // zero. 3393 // zero.
3301 ComputeSafeUint32Operations(); 3394 ComputeSafeUint32Operations();
3302 3395
3303 Canonicalize(); 3396 Canonicalize();
3304 3397
3398 ProcessJSArrayLengths();
3399
3305 // Perform common subexpression elimination and loop-invariant code motion. 3400 // Perform common subexpression elimination and loop-invariant code motion.
3306 if (FLAG_use_gvn) { 3401 if (FLAG_use_gvn) {
3307 HPhase phase("H_Global value numbering", this); 3402 HPhase phase("H_Global value numbering", this);
3308 HGlobalValueNumberer gvn(this, info()); 3403 HGlobalValueNumberer gvn(this, info());
3309 bool removed_side_effects = gvn.Analyze(); 3404 bool removed_side_effects = gvn.Analyze();
3310 // Trigger a second analysis pass to further eliminate duplicate values that 3405 // Trigger a second analysis pass to further eliminate duplicate values that
3311 // could only be discovered by removing side-effect-generating instructions 3406 // could only be discovered by removing side-effect-generating instructions
3312 // during the first pass. 3407 // during the first pass.
3313 if (FLAG_smi_only_arrays && removed_side_effects) { 3408 if (FLAG_smi_only_arrays && removed_side_effects) {
3314 removed_side_effects = gvn.Analyze(); 3409 removed_side_effects = gvn.Analyze();
(...skipping 2842 matching lines...) Expand 10 before | Expand all | Expand 10 after
6157 new(zone()) HLoadExternalArrayPointer(elements); 6252 new(zone()) HLoadExternalArrayPointer(elements);
6158 AddInstruction(external_elements); 6253 AddInstruction(external_elements);
6159 return BuildExternalArrayElementAccess( 6254 return BuildExternalArrayElementAccess(
6160 external_elements, checked_key, val, mapcheck, 6255 external_elements, checked_key, val, mapcheck,
6161 map->elements_kind(), is_store); 6256 map->elements_kind(), is_store);
6162 } 6257 }
6163 ASSERT(fast_smi_only_elements || 6258 ASSERT(fast_smi_only_elements ||
6164 fast_elements || 6259 fast_elements ||
6165 map->has_fast_double_elements()); 6260 map->has_fast_double_elements());
6166 if (map->instance_type() == JS_ARRAY_TYPE) { 6261 if (map->instance_type() == JS_ARRAY_TYPE) {
6167 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck, 6262 length = AddInstruction(HJSArrayLength::Create(
6168 HType::Smi())); 6263 graph(), object, mapcheck, HType::Smi()));
6169 } else { 6264 } else {
6170 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 6265 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
6171 } 6266 }
6172 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, 6267 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length,
6173 ALLOW_SMI_KEY)); 6268 ALLOW_SMI_KEY));
6174 return BuildFastElementAccess(elements, checked_key, val, mapcheck, 6269 return BuildFastElementAccess(elements, checked_key, val, mapcheck,
6175 map->elements_kind(), is_store); 6270 map->elements_kind(), is_store);
6176 } 6271 }
6177 6272
6178 6273
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
6382 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); 6477 HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
6383 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); 6478 HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
6384 HHasInstanceTypeAndBranch* typecheck = 6479 HHasInstanceTypeAndBranch* typecheck =
6385 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); 6480 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE);
6386 typecheck->SetSuccessorAt(0, if_jsarray); 6481 typecheck->SetSuccessorAt(0, if_jsarray);
6387 typecheck->SetSuccessorAt(1, if_fastobject); 6482 typecheck->SetSuccessorAt(1, if_fastobject);
6388 current_block()->Finish(typecheck); 6483 current_block()->Finish(typecheck);
6389 6484
6390 set_current_block(if_jsarray); 6485 set_current_block(if_jsarray);
6391 HInstruction* length; 6486 HInstruction* length;
6392 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck, 6487 length = AddInstruction(HJSArrayLength::Create(
6393 HType::Smi())); 6488 graph(), object, typecheck, HType::Smi()));
6394 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length, 6489 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length,
6395 ALLOW_SMI_KEY)); 6490 ALLOW_SMI_KEY));
6396 access = AddInstruction(BuildFastElementAccess( 6491 access = AddInstruction(BuildFastElementAccess(
6397 elements, checked_key, val, elements_kind_branch, 6492 elements, checked_key, val, elements_kind_branch,
6398 elements_kind, is_store)); 6493 elements_kind, is_store));
6399 if (!is_store) { 6494 if (!is_store) {
6400 Push(access); 6495 Push(access);
6401 } 6496 }
6402 6497
6403 *has_side_effects |= access->HasObservableSideEffects(); 6498 *has_side_effects |= access->HasObservableSideEffects();
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
6588 if (TryArgumentsAccess(expr)) return; 6683 if (TryArgumentsAccess(expr)) return;
6589 6684
6590 CHECK_ALIVE(VisitForValue(expr->obj())); 6685 CHECK_ALIVE(VisitForValue(expr->obj()));
6591 6686
6592 HInstruction* instr = NULL; 6687 HInstruction* instr = NULL;
6593 if (expr->AsProperty()->IsArrayLength()) { 6688 if (expr->AsProperty()->IsArrayLength()) {
6594 HValue* array = Pop(); 6689 HValue* array = Pop();
6595 AddInstruction(new(zone()) HCheckNonSmi(array)); 6690 AddInstruction(new(zone()) HCheckNonSmi(array));
6596 HInstruction* mapcheck = 6691 HInstruction* mapcheck =
6597 AddInstruction(HCheckInstanceType::NewIsJSArray(array, zone())); 6692 AddInstruction(HCheckInstanceType::NewIsJSArray(array, zone()));
6598 instr = new(zone()) HJSArrayLength(array, mapcheck); 6693 instr = HJSArrayLength::Create(graph(), array, mapcheck);
6599 } else if (expr->IsStringLength()) { 6694 } else if (expr->IsStringLength()) {
6600 HValue* string = Pop(); 6695 HValue* string = Pop();
6601 AddInstruction(new(zone()) HCheckNonSmi(string)); 6696 AddInstruction(new(zone()) HCheckNonSmi(string));
6602 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); 6697 AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
6603 instr = new(zone()) HStringLength(string); 6698 instr = new(zone()) HStringLength(string);
6604 } else if (expr->IsStringAccess()) { 6699 } else if (expr->IsStringAccess()) {
6605 CHECK_ALIVE(VisitForValue(expr->key())); 6700 CHECK_ALIVE(VisitForValue(expr->key()));
6606 HValue* index = Pop(); 6701 HValue* index = Pop();
6607 HValue* string = Pop(); 6702 HValue* string = Pop();
6608 HValue* context = environment()->LookupContext(); 6703 HValue* context = environment()->LookupContext();
(...skipping 3450 matching lines...) Expand 10 before | Expand all | Expand 10 after
10059 } 10154 }
10060 } 10155 }
10061 10156
10062 #ifdef DEBUG 10157 #ifdef DEBUG
10063 if (graph_ != NULL) graph_->Verify(false); // No full verify. 10158 if (graph_ != NULL) graph_->Verify(false); // No full verify.
10064 if (allocator_ != NULL) allocator_->Verify(); 10159 if (allocator_ != NULL) allocator_->Verify();
10065 #endif 10160 #endif
10066 } 10161 }
10067 10162
10068 } } // namespace v8::internal 10163 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698