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

Side by Side Diff: src/compiler/simplified-lowering.cc

Issue 640603003: [turbofan] Properly emit bounds checks for typed array element loads. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 2 months 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/compiler/simplified-lowering.h ('k') | test/mjsunit/asm/int32array-outofbounds.js » ('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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/simplified-lowering.h" 5 #include "src/compiler/simplified-lowering.h"
6 6
7 #include "src/base/bits.h" 7 #include "src/base/bits.h"
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/compiler/common-operator.h" 9 #include "src/compiler/common-operator.h"
10 #include "src/compiler/graph-inl.h" 10 #include "src/compiler/graph-inl.h"
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 SetOutput(node, 0); 578 SetOutput(node, 0);
579 if (lower()) lowering->DoStoreField(node); 579 if (lower()) lowering->DoStoreField(node);
580 break; 580 break;
581 } 581 }
582 case IrOpcode::kLoadElement: { 582 case IrOpcode::kLoadElement: {
583 ElementAccess access = ElementAccessOf(node->op()); 583 ElementAccess access = ElementAccessOf(node->op());
584 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); 584 ProcessInput(node, 0, changer_->TypeForBasePointer(access));
585 ProcessInput(node, 1, kMachInt32); // element index 585 ProcessInput(node, 1, kMachInt32); // element index
586 ProcessInput(node, 2, kMachInt32); // length 586 ProcessInput(node, 2, kMachInt32); // length
587 ProcessRemainingInputs(node, 3); 587 ProcessRemainingInputs(node, 3);
588 SetOutput(node, access.machine_type); 588 // Tagged overrides everything if we have to do a typed array bounds
589 if (lower()) lowering->DoLoadElement(node); 589 // check, because we may need to return undefined then.
590 MachineType output_type =
591 (access.bounds_check == kTypedArrayBoundsCheck &&
592 (use & kRepTagged))
593 ? kMachAnyTagged
594 : access.machine_type;
595 SetOutput(node, output_type);
596 if (lower()) lowering->DoLoadElement(node, output_type);
590 break; 597 break;
591 } 598 }
592 case IrOpcode::kStoreElement: { 599 case IrOpcode::kStoreElement: {
593 ElementAccess access = ElementAccessOf(node->op()); 600 ElementAccess access = ElementAccessOf(node->op());
594 ProcessInput(node, 0, changer_->TypeForBasePointer(access)); 601 ProcessInput(node, 0, changer_->TypeForBasePointer(access));
595 ProcessInput(node, 1, kMachInt32); // element index 602 ProcessInput(node, 1, kMachInt32); // element index
596 ProcessInput(node, 2, kMachInt32); // length 603 ProcessInput(node, 2, kMachInt32); // length
597 ProcessInput(node, 3, access.machine_type); 604 ProcessInput(node, 3, access.machine_type);
598 ProcessRemainingInputs(node, 4); 605 ProcessRemainingInputs(node, 4);
599 SetOutput(node, 0); 606 SetOutput(node, 0);
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 index = graph()->NewNode(machine()->Int32Mul(), 866 index = graph()->NewNode(machine()->Int32Mul(),
860 jsgraph()->Int32Constant(element_size), index); 867 jsgraph()->Int32Constant(element_size), index);
861 } 868 }
862 int fixed_offset = access.header_size - access.tag(); 869 int fixed_offset = access.header_size - access.tag();
863 if (fixed_offset == 0) return index; 870 if (fixed_offset == 0) return index;
864 return graph()->NewNode(machine()->Int32Add(), index, 871 return graph()->NewNode(machine()->Int32Add(), index,
865 jsgraph()->Int32Constant(fixed_offset)); 872 jsgraph()->Int32Constant(fixed_offset));
866 } 873 }
867 874
868 875
869 void SimplifiedLowering::DoLoadElement(Node* node) { 876 void SimplifiedLowering::DoLoadElement(Node* node, MachineType output_type) {
Michael Starzinger 2014/10/08 09:25:31 Instead of passing the output_type as an argument
Benedikt Meurer 2014/10/08 10:54:58 As discussed offline: Not possible.
870 const ElementAccess& access = ElementAccessOf(node->op()); 877 const ElementAccess& access = ElementAccessOf(node->op());
871 node->set_op(machine()->Load(access.machine_type)); 878 const Operator* op = machine()->Load(access.machine_type);
872 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); 879 Node* key = node->InputAt(1);
873 node->RemoveInput(2); 880 Node* index = ComputeIndex(access, key);
881 if (access.bounds_check == kNoBoundsCheck) {
882 DCHECK_EQ(access.machine_type, output_type);
883 node->set_op(op);
884 node->ReplaceInput(1, index);
885 node->RemoveInput(2);
886 } else {
887 DCHECK_EQ(kTypedArrayBoundsCheck, access.bounds_check);
888
889 Node* base = node->InputAt(0);
890 Node* length = node->InputAt(2);
891 Node* effect = node->InputAt(3);
892 Node* control = node->InputAt(4);
893
894 Node* check = graph()->NewNode(machine()->Uint32LessThan(), key, length);
895 Node* branch = graph()->NewNode(common()->Branch(), check, control);
896
897 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
898 Node* load = graph()->NewNode(op, base, index, effect, if_true);
899 Node* result = load;
900 if (output_type & kRepTagged) {
901 // TODO(turbofan): This is ugly as hell!
Michael Starzinger 2014/10/08 09:25:31 I concur. :)
902 SimplifiedOperatorBuilder simplified(graph()->zone());
903 RepresentationChanger changer(jsgraph(), &simplified,
904 graph()->zone()->isolate());
905 result = changer.GetTaggedRepresentationFor(result, access.machine_type);
906 }
907
908 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
909 Node* undefined;
910 if (output_type & kRepTagged) {
911 DCHECK(!(access.machine_type & kRepTagged));
912 undefined = jsgraph()->UndefinedConstant();
913 } else if (output_type & kRepFloat32) {
914 undefined = jsgraph()->Float32Constant(0.0f);
915 } else if (output_type & kRepFloat64) {
916 undefined = jsgraph()->Float64Constant(0.0);
917 } else {
918 undefined = jsgraph()->Int32Constant(0);
919 }
920
921 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
922 Node* phi = graph()->NewNode(common()->EffectPhi(2), load, effect, merge);
923
924 // Replace effect uses of node with the effect phi.
925 for (UseIter i = node->uses().begin(); i != node->uses().end();) {
926 if (NodeProperties::IsEffectEdge(i.edge())) {
927 i = i.UpdateToAndIncrement(phi);
928 } else {
929 ++i;
930 }
931 }
932
933 node->set_op(common()->Phi(output_type, 2));
934 node->ReplaceInput(0, result);
935 node->ReplaceInput(1, undefined);
936 node->ReplaceInput(2, merge);
937 node->TrimInputCount(3);
938 }
874 } 939 }
875 940
876 941
877 void SimplifiedLowering::DoStoreElement(Node* node) { 942 void SimplifiedLowering::DoStoreElement(Node* node) {
878 const ElementAccess& access = ElementAccessOf(node->op()); 943 const ElementAccess& access = ElementAccessOf(node->op());
879 const Operator* op = machine()->Store(StoreRepresentation( 944 const Operator* op = machine()->Store(StoreRepresentation(
880 access.machine_type, 945 access.machine_type,
881 ComputeWriteBarrierKind(access.base_is_tagged, access.machine_type, 946 ComputeWriteBarrierKind(access.base_is_tagged, access.machine_type,
882 access.type))); 947 access.type)));
883 Node* key = node->InputAt(1); 948 Node* key = node->InputAt(1);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) { 1029 void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) {
965 node->set_op(machine()->IntLessThanOrEqual()); 1030 node->set_op(machine()->IntLessThanOrEqual());
966 node->ReplaceInput(0, StringComparison(node, true)); 1031 node->ReplaceInput(0, StringComparison(node, true));
967 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL)); 1032 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
968 } 1033 }
969 1034
970 1035
971 } // namespace compiler 1036 } // namespace compiler
972 } // namespace internal 1037 } // namespace internal
973 } // namespace v8 1038 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/simplified-lowering.h ('k') | test/mjsunit/asm/int32array-outofbounds.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698