Index: src/compiler/simplified-lowering.cc |
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc |
index 3fc735a09c0ff00c5b1507de49159a22a104b34f..b86837d244c0e880e667a9574b885bbae095d52a 100644 |
--- a/src/compiler/simplified-lowering.cc |
+++ b/src/compiler/simplified-lowering.cc |
@@ -4,6 +4,8 @@ |
#include "src/compiler/simplified-lowering.h" |
+#include <limits> |
+ |
#include "src/base/bits.h" |
#include "src/code-factory.h" |
#include "src/compiler/common-operator.h" |
@@ -665,8 +667,15 @@ class RepresentationSelector { |
ProcessInput(node, 1, kMachInt32); // element index |
ProcessInput(node, 2, kMachInt32); // length |
ProcessRemainingInputs(node, 3); |
- SetOutput(node, access.machine_type); |
- if (lower()) lowering->DoLoadElement(node); |
+ // Tagged overrides everything if we have to do a typed array bounds |
+ // check, because we may need to return undefined then. |
+ MachineType output_type = |
+ (access.bounds_check == kTypedArrayBoundsCheck && |
+ (use & kRepTagged)) |
+ ? kMachAnyTagged |
+ : access.machine_type; |
+ SetOutput(node, output_type); |
+ if (lower()) lowering->DoLoadElement(node, output_type); |
break; |
} |
case IrOpcode::kStoreElement: { |
@@ -957,11 +966,71 @@ Node* SimplifiedLowering::ComputeIndex(const ElementAccess& access, |
} |
-void SimplifiedLowering::DoLoadElement(Node* node) { |
+void SimplifiedLowering::DoLoadElement(Node* node, MachineType output_type) { |
const ElementAccess& access = ElementAccessOf(node->op()); |
- node->set_op(machine()->Load(access.machine_type)); |
- node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); |
- node->RemoveInput(2); |
+ const Operator* op = machine()->Load(access.machine_type); |
+ Node* key = node->InputAt(1); |
+ Node* index = ComputeIndex(access, key); |
+ if (access.bounds_check == kNoBoundsCheck) { |
+ DCHECK_EQ(access.machine_type, output_type); |
+ node->set_op(op); |
+ node->ReplaceInput(1, index); |
+ node->RemoveInput(2); |
+ } else { |
+ DCHECK_EQ(kTypedArrayBoundsCheck, access.bounds_check); |
+ |
+ Node* base = node->InputAt(0); |
+ Node* length = node->InputAt(2); |
+ Node* effect = node->InputAt(3); |
+ Node* control = node->InputAt(4); |
+ |
+ Node* check = graph()->NewNode(machine()->Uint32LessThan(), key, length); |
+ Node* branch = graph()->NewNode(common()->Branch(), check, control); |
+ |
+ Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
+ Node* load = graph()->NewNode(op, base, index, effect, if_true); |
+ Node* result = load; |
+ if (output_type & kRepTagged) { |
+ // TODO(turbofan): This is ugly as hell! |
+ SimplifiedOperatorBuilder simplified(graph()->zone()); |
+ RepresentationChanger changer(jsgraph(), &simplified, |
+ graph()->zone()->isolate()); |
+ result = changer.GetTaggedRepresentationFor(result, access.machine_type); |
+ } |
+ |
+ Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
+ Node* undefined; |
+ if (output_type & kRepTagged) { |
+ DCHECK(!(access.machine_type & kRepTagged)); |
+ undefined = jsgraph()->UndefinedConstant(); |
+ } else if (output_type & kRepFloat32) { |
+ undefined = |
+ jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN()); |
+ } else if (output_type & kRepFloat64) { |
+ undefined = |
+ jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN()); |
+ } else { |
+ undefined = jsgraph()->Int32Constant(0); |
+ } |
+ |
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
+ Node* phi = graph()->NewNode(common()->EffectPhi(2), load, effect, merge); |
+ |
+ // Replace effect uses of node with the effect phi. |
+ for (UseIter i = node->uses().begin(); i != node->uses().end();) { |
+ if (NodeProperties::IsEffectEdge(i.edge())) { |
+ i = i.UpdateToAndIncrement(phi); |
+ } else { |
+ ++i; |
+ } |
+ } |
+ |
+ node->set_op(common()->Phi(output_type, 2)); |
+ node->ReplaceInput(0, result); |
+ node->ReplaceInput(1, undefined); |
+ node->ReplaceInput(2, merge); |
+ node->TrimInputCount(3); |
+ } |
} |