Add support for adding an external and a tagged pointer
This will be used to compute the base pointer of the new unified representation for both on-heap and external typed arrays. The idea is that either the external or the tagged pointer is 0 (although in practice, if the tagged pointer is non-0, the external pointer will contain the offset from the start of the on-heap typed array to the data in the on-heap typed array). The HAdd is marked as depending on new-space promotion, as the tagged pointer might move during GC, and so the result of the addition needs to be recomputed. BUG=v8:3996 R=jarin@chromium.org LOG=n Review URL: https://codereview.chromium.org/1244693002 Cr-Commit-Position: refs/heads/master@{#29760}
This commit is contained in:
parent
df2d1ef979
commit
4e263bc581
@ -1675,8 +1675,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
||||
}
|
||||
return result;
|
||||
} else if (instr->representation().IsExternal()) {
|
||||
DCHECK(instr->left()->representation().IsExternal());
|
||||
DCHECK(instr->right()->representation().IsInteger32());
|
||||
DCHECK(instr->IsConsistentExternalRepresentation());
|
||||
DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
|
||||
LOperand* left = UseRegisterAtStart(instr->left());
|
||||
LOperand* right = UseOrConstantAtStart(instr->right());
|
||||
|
@ -901,8 +901,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
||||
}
|
||||
return result;
|
||||
} else if (instr->representation().IsExternal()) {
|
||||
DCHECK(instr->left()->representation().IsExternal());
|
||||
DCHECK(instr->right()->representation().IsInteger32());
|
||||
DCHECK(instr->IsConsistentExternalRepresentation());
|
||||
DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
|
||||
LOperand* left = UseRegisterAtStart(instr->left());
|
||||
LOperand* right = UseRegisterOrConstantAtStart(instr->right());
|
||||
|
@ -1432,6 +1432,17 @@ HValue* HBitwise::Canonicalize() {
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
HInstruction* HAdd::New(Isolate* isolate, Zone* zone, HValue* context,
|
||||
HValue* left, HValue* right, Strength strength,
|
||||
ExternalAddType external_add_type) {
|
||||
// For everything else, you should use the other factory method without
|
||||
// ExternalAddType.
|
||||
DCHECK_EQ(external_add_type, AddOfExternalAndTagged);
|
||||
return new (zone) HAdd(context, left, right, strength, external_add_type);
|
||||
}
|
||||
|
||||
|
||||
Representation HAdd::RepresentationFromInputs() {
|
||||
Representation left_rep = left()->representation();
|
||||
if (left_rep.IsExternal()) {
|
||||
@ -1445,7 +1456,11 @@ Representation HAdd::RequiredInputRepresentation(int index) {
|
||||
if (index == 2) {
|
||||
Representation left_rep = left()->representation();
|
||||
if (left_rep.IsExternal()) {
|
||||
return Representation::Integer32();
|
||||
if (external_add_type_ == AddOfExternalAndTagged) {
|
||||
return Representation::Tagged();
|
||||
} else {
|
||||
return Representation::Integer32();
|
||||
}
|
||||
}
|
||||
}
|
||||
return HArithmeticBinaryOperation::RequiredInputRepresentation(index);
|
||||
|
@ -4830,11 +4830,21 @@ class HPower final : public HTemplateInstruction<2> {
|
||||
};
|
||||
|
||||
|
||||
enum ExternalAddType {
|
||||
AddOfExternalAndTagged,
|
||||
AddOfExternalAndInt32,
|
||||
NoExternalAdd
|
||||
};
|
||||
|
||||
|
||||
class HAdd final : public HArithmeticBinaryOperation {
|
||||
public:
|
||||
static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
|
||||
HValue* left, HValue* right,
|
||||
Strength strength = Strength::WEAK);
|
||||
static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context,
|
||||
HValue* left, HValue* right, Strength strength,
|
||||
ExternalAddType external_add_type);
|
||||
|
||||
// Add is only commutative if two integer values are added and not if two
|
||||
// tagged values are added (because it might be a String concatenation).
|
||||
@ -4877,6 +4887,14 @@ class HAdd final : public HArithmeticBinaryOperation {
|
||||
|
||||
Representation RequiredInputRepresentation(int index) override;
|
||||
|
||||
bool IsConsistentExternalRepresentation() {
|
||||
return left()->representation().IsExternal() &&
|
||||
((external_add_type_ == AddOfExternalAndInt32 &&
|
||||
right()->representation().IsInteger32()) ||
|
||||
(external_add_type_ == AddOfExternalAndTagged &&
|
||||
right()->representation().IsTagged()));
|
||||
}
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(Add)
|
||||
|
||||
protected:
|
||||
@ -4885,10 +4903,35 @@ class HAdd final : public HArithmeticBinaryOperation {
|
||||
Range* InferRange(Zone* zone) override;
|
||||
|
||||
private:
|
||||
HAdd(HValue* context, HValue* left, HValue* right, Strength strength)
|
||||
: HArithmeticBinaryOperation(context, left, right, strength) {
|
||||
HAdd(HValue* context, HValue* left, HValue* right, Strength strength,
|
||||
ExternalAddType external_add_type = NoExternalAdd)
|
||||
: HArithmeticBinaryOperation(context, left, right, strength),
|
||||
external_add_type_(external_add_type) {
|
||||
SetFlag(kCanOverflow);
|
||||
switch (external_add_type_) {
|
||||
case AddOfExternalAndTagged:
|
||||
DCHECK(left->representation().IsExternal());
|
||||
DCHECK(right->representation().IsTagged());
|
||||
SetDependsOnFlag(kNewSpacePromotion);
|
||||
break;
|
||||
|
||||
case NoExternalAdd:
|
||||
// This is a bit of a hack: The call to this constructor is generated
|
||||
// by a macro that also supports sub and mul, so it doesn't pass in
|
||||
// a value for external_add_type but uses the default.
|
||||
if (left->representation().IsExternal()) {
|
||||
external_add_type_ = AddOfExternalAndInt32;
|
||||
}
|
||||
break;
|
||||
|
||||
case AddOfExternalAndInt32:
|
||||
// See comment above.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ExternalAddType external_add_type_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1629,8 +1629,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
||||
} else if (instr->representation().IsDouble()) {
|
||||
return DoArithmeticD(Token::ADD, instr);
|
||||
} else if (instr->representation().IsExternal()) {
|
||||
DCHECK(instr->left()->representation().IsExternal());
|
||||
DCHECK(instr->right()->representation().IsInteger32());
|
||||
DCHECK(instr->IsConsistentExternalRepresentation());
|
||||
DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
|
||||
bool use_lea = LAddI::UseLea(instr);
|
||||
LOperand* left = UseRegisterAtStart(instr->left());
|
||||
|
@ -1622,8 +1622,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
||||
}
|
||||
return result;
|
||||
} else if (instr->representation().IsExternal()) {
|
||||
DCHECK(instr->left()->representation().IsExternal());
|
||||
DCHECK(instr->right()->representation().IsInteger32());
|
||||
DCHECK(instr->IsConsistentExternalRepresentation());
|
||||
DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
|
||||
LOperand* left = UseRegisterAtStart(instr->left());
|
||||
LOperand* right = UseOrConstantAtStart(instr->right());
|
||||
|
@ -1630,8 +1630,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
||||
}
|
||||
return result;
|
||||
} else if (instr->representation().IsExternal()) {
|
||||
DCHECK(instr->left()->representation().IsExternal());
|
||||
DCHECK(instr->right()->representation().IsInteger32());
|
||||
DCHECK(instr->IsConsistentExternalRepresentation());
|
||||
DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
|
||||
LOperand* left = UseRegisterAtStart(instr->left());
|
||||
LOperand* right = UseRegisterOrConstantAtStart(instr->right());
|
||||
|
@ -1645,8 +1645,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
||||
}
|
||||
return result;
|
||||
} else if (instr->representation().IsExternal()) {
|
||||
DCHECK(instr->left()->representation().IsExternal());
|
||||
DCHECK(instr->right()->representation().IsInteger32());
|
||||
DCHECK(instr->IsConsistentExternalRepresentation());
|
||||
DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
|
||||
LOperand* left = UseRegisterAtStart(instr->left());
|
||||
LOperand* right = UseOrConstantAtStart(instr->right());
|
||||
|
@ -1619,8 +1619,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
||||
}
|
||||
return result;
|
||||
} else if (instr->representation().IsExternal()) {
|
||||
DCHECK(instr->left()->representation().IsExternal());
|
||||
DCHECK(instr->right()->representation().IsInteger32());
|
||||
DCHECK(instr->IsConsistentExternalRepresentation());
|
||||
DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
|
||||
bool use_lea = LAddI::UseLea(instr);
|
||||
LOperand* left = UseRegisterAtStart(instr->left());
|
||||
|
@ -1639,8 +1639,7 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
||||
} else if (instr->representation().IsDouble()) {
|
||||
return DoArithmeticD(Token::ADD, instr);
|
||||
} else if (instr->representation().IsExternal()) {
|
||||
DCHECK(instr->left()->representation().IsExternal());
|
||||
DCHECK(instr->right()->representation().IsInteger32());
|
||||
DCHECK(instr->IsConsistentExternalRepresentation());
|
||||
DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
|
||||
bool use_lea = LAddI::UseLea(instr);
|
||||
LOperand* left = UseRegisterAtStart(instr->left());
|
||||
|
Loading…
Reference in New Issue
Block a user