Index: src/compiler/effect-control-linearizer.cc |
diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc |
index 27da109b500a56e7fea89a5949a447ff9adacda8..b734255efac41bf7de8842c7b0d91c0849f5e259 100644 |
--- a/src/compiler/effect-control-linearizer.cc |
+++ b/src/compiler/effect-control-linearizer.cc |
@@ -791,6 +791,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, |
case IrOpcode::kTransitionElementsKind: |
LowerTransitionElementsKind(node); |
break; |
+ case IrOpcode::kLoadFieldByIndex: |
+ result = LowerLoadFieldByIndex(node); |
+ break; |
case IrOpcode::kLoadTypedElement: |
result = LowerLoadTypedElement(node); |
break; |
@@ -2554,6 +2557,107 @@ void EffectControlLinearizer::LowerTransitionElementsKind(Node* node) { |
__ Bind(&done); |
} |
+Node* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) { |
+ Node* object = node->InputAt(0); |
+ Node* index = node->InputAt(1); |
+ Node* zero = __ IntPtrConstant(0); |
+ Node* one = __ IntPtrConstant(1); |
+ |
+ // Sign-extend the {index} on 64-bit architectures. |
+ if (machine()->Is64()) { |
+ index = __ ChangeInt32ToInt64(index); |
+ } |
+ |
+ auto if_double = __ MakeDeferredLabel<1>(); |
+ auto done = __ MakeLabel<3>(MachineRepresentation::kTagged); |
+ |
+ // Check if field is a mutable double field. |
+ __ GotoUnless(__ WordEqual(__ WordAnd(index, one), zero), &if_double); |
+ |
+ // The field is a proper Tagged field on {object}. The {index} is shifted |
+ // to the left by one in the code below. |
+ { |
+ // Check if field is in-object or out-of-object. |
+ auto if_outofobject = __ MakeLabel<1>(); |
+ __ GotoIf(__ IntLessThan(index, zero), &if_outofobject); |
+ |
+ // The field is located in the {object} itself. |
+ { |
+ Node* offset = |
+ __ IntAdd(__ WordShl(index, __ IntPtrConstant(kPointerSizeLog2 - 1)), |
+ __ IntPtrConstant(JSObject::kHeaderSize - kHeapObjectTag)); |
+ Node* result = __ Load(MachineType::AnyTagged(), object, offset); |
+ __ Goto(&done, result); |
+ } |
+ |
+ // The field is located in the properties backing store of {object}. |
+ // The {index} is equal to the negated out of property index plus 1. |
+ __ Bind(&if_outofobject); |
+ { |
+ Node* properties = |
+ __ LoadField(AccessBuilder::ForJSObjectProperties(), object); |
+ Node* offset = |
+ __ IntAdd(__ WordShl(__ IntSub(zero, index), |
+ __ IntPtrConstant(kPointerSizeLog2 - 1)), |
+ __ IntPtrConstant((FixedArray::kHeaderSize - kPointerSize) - |
+ kHeapObjectTag)); |
+ Node* result = __ Load(MachineType::AnyTagged(), properties, offset); |
+ __ Goto(&done, result); |
+ } |
+ } |
+ |
+ // The field is a Double field, either unboxed in the object on 64-bit |
+ // architectures, or as MutableHeapNumber. |
+ __ Bind(&if_double); |
+ { |
+ auto done_double = __ MakeLabel<2>(MachineRepresentation::kFloat64); |
+ |
+ index = __ WordSar(index, one); |
+ |
+ // Check if field is in-object or out-of-object. |
+ auto if_outofobject = __ MakeLabel<1>(); |
+ __ GotoIf(__ IntLessThan(index, zero), &if_outofobject); |
+ |
+ // The field is located in the {object} itself. |
+ { |
+ Node* offset = |
+ __ IntAdd(__ WordShl(index, __ IntPtrConstant(kPointerSizeLog2)), |
+ __ IntPtrConstant(JSObject::kHeaderSize - kHeapObjectTag)); |
+ if (FLAG_unbox_double_fields) { |
+ Node* result = __ Load(MachineType::Float64(), object, offset); |
+ __ Goto(&done_double, result); |
+ } else { |
+ Node* result = __ Load(MachineType::AnyTagged(), object, offset); |
+ result = __ LoadField(AccessBuilder::ForHeapNumberValue(), result); |
+ __ Goto(&done_double, result); |
+ } |
+ } |
+ |
+ __ Bind(&if_outofobject); |
+ { |
+ Node* properties = |
+ __ LoadField(AccessBuilder::ForJSObjectProperties(), object); |
+ Node* offset = |
+ __ IntAdd(__ WordShl(__ IntSub(zero, index), |
+ __ IntPtrConstant(kPointerSizeLog2)), |
+ __ IntPtrConstant((FixedArray::kHeaderSize - kPointerSize) - |
+ kHeapObjectTag)); |
+ Node* result = __ Load(MachineType::AnyTagged(), properties, offset); |
+ result = __ LoadField(AccessBuilder::ForHeapNumberValue(), result); |
+ __ Goto(&done_double, result); |
+ } |
+ |
+ __ Bind(&done_double); |
+ { |
+ Node* result = AllocateHeapNumberWithValue(done_double.PhiAt(0)); |
+ __ Goto(&done, result); |
+ } |
+ } |
+ |
+ __ Bind(&done); |
+ return done.PhiAt(0); |
+} |
+ |
Node* EffectControlLinearizer::LowerLoadTypedElement(Node* node) { |
ExternalArrayType array_type = ExternalArrayTypeOf(node->op()); |
Node* buffer = node->InputAt(0); |