[turbofan] Introduce an ExternalPointer type.
This adds a new ExternalPointer type, which is an Internal type that is used for ExternalReferences and other pointer values, like the pointers into the asm.js heap. It also adds a PointerConstant operator, which we use to represents these raw constants (we can probably remove that particular operator again once WebAssembly ships with the validator). R=mvstanton@chromium.org BUG=v8:5267,v8:5270 Review-Url: https://codereview.chromium.org/2494753003 Cr-Commit-Position: refs/heads/master@{#40923}
This commit is contained in:
parent
e3c7324a2e
commit
7d24f1aefa
@ -357,7 +357,7 @@ FieldAccess AccessBuilder::ForFixedTypedArrayBaseExternalPointer() {
|
||||
FieldAccess access = {kTaggedBase,
|
||||
FixedTypedArrayBase::kExternalPointerOffset,
|
||||
MaybeHandle<Name>(),
|
||||
Type::OtherInternal(),
|
||||
Type::ExternalPointer(),
|
||||
MachineType::Pointer(),
|
||||
kNoWriteBarrier};
|
||||
return access;
|
||||
@ -512,7 +512,7 @@ FieldAccess AccessBuilder::ForExternalStringResourceData() {
|
||||
FieldAccess access = {kTaggedBase,
|
||||
ExternalString::kResourceDataOffset,
|
||||
Handle<Name>(),
|
||||
Type::OtherInternal(),
|
||||
Type::ExternalPointer(),
|
||||
MachineType::Pointer(),
|
||||
kNoWriteBarrier};
|
||||
return access;
|
||||
|
@ -3780,7 +3780,7 @@ Node* AstGraphBuilder::BuildReturn(Node* return_value) {
|
||||
return_value =
|
||||
NewNode(javascript()->CallRuntime(Runtime::kTraceExit), return_value);
|
||||
}
|
||||
Node* pop_node = jsgraph()->Int32Constant(0);
|
||||
Node* pop_node = jsgraph()->ZeroConstant();
|
||||
Node* control = NewNode(common()->Return(), pop_node, return_value);
|
||||
UpdateControlDependencyToLeaveFunction(control);
|
||||
return control;
|
||||
|
@ -1734,7 +1734,7 @@ void BytecodeGraphBuilder::VisitStackCheck() {
|
||||
|
||||
void BytecodeGraphBuilder::VisitReturn() {
|
||||
BuildLoopExitsForFunctionExit();
|
||||
Node* pop_node = jsgraph()->Int32Constant(0);
|
||||
Node* pop_node = jsgraph()->ZeroConstant();
|
||||
Node* control =
|
||||
NewNode(common()->Return(), pop_node, environment()->LookupAccumulator());
|
||||
MergeControlToLeaveFunction(control);
|
||||
|
@ -859,9 +859,12 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation,
|
||||
handle(reinterpret_cast<Smi*>(constant.ToInt32()), isolate());
|
||||
DCHECK(constant_object->IsSmi());
|
||||
} else {
|
||||
// TODO(jarin,bmeurer): We currently pass in raw pointers to the
|
||||
// JSFunction::entry here. We should really consider fixing this.
|
||||
DCHECK(type == MachineType::Int32() ||
|
||||
type == MachineType::Uint32() ||
|
||||
type.representation() == MachineRepresentation::kBit ||
|
||||
type.representation() == MachineRepresentation::kWord32 ||
|
||||
type.representation() == MachineRepresentation::kNone);
|
||||
DCHECK(type.representation() != MachineRepresentation::kNone ||
|
||||
constant.ToInt32() == FrameStateDescriptor::kImpossibleValue);
|
||||
@ -873,7 +876,10 @@ void CodeGenerator::AddTranslationForOperand(Translation* translation,
|
||||
case Constant::kInt64:
|
||||
// When pointers are 8 bytes, we can use int64 constants to represent
|
||||
// Smis.
|
||||
DCHECK(type.representation() == MachineRepresentation::kTagged ||
|
||||
// TODO(jarin,bmeurer): We currently pass in raw pointers to the
|
||||
// JSFunction::entry here. We should really consider fixing this.
|
||||
DCHECK(type.representation() == MachineRepresentation::kWord64 ||
|
||||
type.representation() == MachineRepresentation::kTagged ||
|
||||
type.representation() == MachineRepresentation::kTaggedSigned);
|
||||
DCHECK_EQ(8, kPointerSize);
|
||||
constant_object =
|
||||
|
@ -45,6 +45,10 @@ class CommonNodeCache final {
|
||||
|
||||
Node** FindExternalConstant(ExternalReference value);
|
||||
|
||||
Node** FindPointerConstant(intptr_t value) {
|
||||
return pointer_constants_.Find(zone(), value);
|
||||
}
|
||||
|
||||
Node** FindNumberConstant(double value) {
|
||||
// We canonicalize double constants at the bit representation level.
|
||||
return number_constants_.Find(zone(), bit_cast<int64_t>(value));
|
||||
@ -73,6 +77,7 @@ class CommonNodeCache final {
|
||||
Int32NodeCache float32_constants_;
|
||||
Int64NodeCache float64_constants_;
|
||||
IntPtrNodeCache external_constants_;
|
||||
IntPtrNodeCache pointer_constants_;
|
||||
Int64NodeCache number_constants_;
|
||||
IntPtrNodeCache heap_constants_;
|
||||
RelocInt32NodeCache relocatable_int32_constants_;
|
||||
|
@ -880,6 +880,13 @@ const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) {
|
||||
value); // parameter
|
||||
}
|
||||
|
||||
const Operator* CommonOperatorBuilder::PointerConstant(intptr_t value) {
|
||||
return new (zone()) Operator1<intptr_t>( // --
|
||||
IrOpcode::kPointerConstant, Operator::kPure, // opcode
|
||||
"PointerConstant", // name
|
||||
0, 0, 0, 1, 0, 0, // counts
|
||||
value); // parameter
|
||||
}
|
||||
|
||||
const Operator* CommonOperatorBuilder::HeapConstant(
|
||||
const Handle<HeapObject>& value) {
|
||||
|
@ -224,6 +224,7 @@ class V8_EXPORT_PRIVATE CommonOperatorBuilder final
|
||||
const Operator* Float64Constant(volatile double);
|
||||
const Operator* ExternalConstant(const ExternalReference&);
|
||||
const Operator* NumberConstant(volatile double);
|
||||
const Operator* PointerConstant(intptr_t);
|
||||
const Operator* HeapConstant(const Handle<HeapObject>&);
|
||||
|
||||
const Operator* RelocatableInt32Constant(int32_t value,
|
||||
|
@ -674,8 +674,8 @@ Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
|
||||
handle(Map::cast(native_context()->get(function_map_index)), isolate()));
|
||||
// Note that it is only safe to embed the raw entry point of the compile
|
||||
// lazy stub into the code, because that stub is immortal and immovable.
|
||||
Node* compile_entry = jsgraph()->IntPtrConstant(reinterpret_cast<intptr_t>(
|
||||
jsgraph()->isolate()->builtins()->CompileLazy()->entry()));
|
||||
Node* compile_entry = jsgraph()->PointerConstant(
|
||||
jsgraph()->isolate()->builtins()->CompileLazy()->entry());
|
||||
Node* empty_fixed_array = jsgraph()->EmptyFixedArrayConstant();
|
||||
Node* empty_literals_array = jsgraph()->EmptyLiteralsArrayConstant();
|
||||
Node* the_hole = jsgraph()->TheHoleConstant();
|
||||
|
@ -242,6 +242,13 @@ Node* JSGraph::Float64Constant(double value) {
|
||||
return *loc;
|
||||
}
|
||||
|
||||
Node* JSGraph::PointerConstant(intptr_t value) {
|
||||
Node** loc = cache_.FindPointerConstant(value);
|
||||
if (*loc == nullptr) {
|
||||
*loc = graph()->NewNode(common()->PointerConstant(value));
|
||||
}
|
||||
return *loc;
|
||||
}
|
||||
|
||||
Node* JSGraph::ExternalConstant(ExternalReference reference) {
|
||||
Node** loc = cache_.FindExternalConstant(reference);
|
||||
|
@ -108,10 +108,6 @@ class V8_EXPORT_PRIVATE JSGraph : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
return machine()->Is32() ? Int32Constant(static_cast<int32_t>(value))
|
||||
: Int64Constant(static_cast<int64_t>(value));
|
||||
}
|
||||
template <typename T>
|
||||
Node* PointerConstant(T* value) {
|
||||
return IntPtrConstant(bit_cast<intptr_t>(value));
|
||||
}
|
||||
|
||||
Node* RelocatableInt32Constant(int32_t value, RelocInfo::Mode rmode);
|
||||
Node* RelocatableInt64Constant(int64_t value, RelocInfo::Mode rmode);
|
||||
@ -123,6 +119,13 @@ class V8_EXPORT_PRIVATE JSGraph : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
// Creates a Float64Constant node, usually canonicalized.
|
||||
Node* Float64Constant(double value);
|
||||
|
||||
// Creates a PointerConstant node (asm.js only).
|
||||
Node* PointerConstant(intptr_t value);
|
||||
template <typename T>
|
||||
Node* PointerConstant(T* value) {
|
||||
return PointerConstant(bit_cast<intptr_t>(value));
|
||||
}
|
||||
|
||||
// Creates an ExternalConstant node, usually canonicalized.
|
||||
Node* ExternalConstant(ExternalReference ref);
|
||||
Node* ExternalConstant(Runtime::FunctionId function_id);
|
||||
|
@ -41,6 +41,7 @@
|
||||
V(Float64Constant) \
|
||||
V(ExternalConstant) \
|
||||
V(NumberConstant) \
|
||||
V(PointerConstant) \
|
||||
V(HeapConstant) \
|
||||
V(RelocatableInt32Constant) \
|
||||
V(RelocatableInt64Constant)
|
||||
|
@ -858,26 +858,8 @@ class RepresentationSelector {
|
||||
return MachineRepresentation::kTagged;
|
||||
} else if (type->Is(Type::Number())) {
|
||||
return MachineRepresentation::kFloat64;
|
||||
} else if (type->Is(Type::Internal())) {
|
||||
// We mark (u)int64 as Type::Internal.
|
||||
// TODO(jarin) This is a workaround for our lack of (u)int64
|
||||
// types. This can be removed once we can represent (u)int64
|
||||
// unambiguously. (At the moment internal objects, such as the hole,
|
||||
// are also Type::Internal()).
|
||||
bool is_word64 = GetInfo(node->InputAt(0))->representation() ==
|
||||
MachineRepresentation::kWord64;
|
||||
#ifdef DEBUG
|
||||
if (node->opcode() != IrOpcode::kTypeGuard) {
|
||||
// Check that all the inputs agree on being Word64.
|
||||
DCHECK_EQ(IrOpcode::kPhi, node->opcode()); // This only works for phis.
|
||||
for (int i = 1; i < node->op()->ValueInputCount(); i++) {
|
||||
DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() ==
|
||||
MachineRepresentation::kWord64);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return is_word64 ? MachineRepresentation::kWord64
|
||||
: MachineRepresentation::kTagged;
|
||||
} else if (type->Is(Type::ExternalPointer())) {
|
||||
return MachineType::PointerRepresentation();
|
||||
}
|
||||
return MachineRepresentation::kTagged;
|
||||
}
|
||||
@ -1015,7 +997,15 @@ class RepresentationSelector {
|
||||
void VisitObjectState(Node* node) {
|
||||
if (propagate()) {
|
||||
for (int i = 0; i < node->InputCount(); i++) {
|
||||
EnqueueInput(node, i, UseInfo::Any());
|
||||
Node* input = node->InputAt(i);
|
||||
Type* input_type = TypeOf(input);
|
||||
// TODO(turbofan): Special treatment for ExternalPointer here,
|
||||
// to avoid incompatible truncations. We really need a story
|
||||
// for the JSFunction::entry field.
|
||||
UseInfo use_info = input_type->Is(Type::ExternalPointer())
|
||||
? UseInfo::PointerInt()
|
||||
: UseInfo::Any();
|
||||
EnqueueInput(node, i, use_info);
|
||||
}
|
||||
} else if (lower()) {
|
||||
Zone* zone = jsgraph_->zone();
|
||||
@ -1026,15 +1016,22 @@ class RepresentationSelector {
|
||||
Node* input = node->InputAt(i);
|
||||
NodeInfo* input_info = GetInfo(input);
|
||||
Type* input_type = TypeOf(input);
|
||||
MachineRepresentation rep = input_type->IsInhabited()
|
||||
? input_info->representation()
|
||||
: MachineRepresentation::kNone;
|
||||
MachineType machine_type(rep, DeoptValueSemanticOf(input_type));
|
||||
DCHECK(machine_type.representation() !=
|
||||
MachineRepresentation::kWord32 ||
|
||||
machine_type.semantic() == MachineSemantic::kInt32 ||
|
||||
machine_type.semantic() == MachineSemantic::kUint32);
|
||||
(*types)[i] = machine_type;
|
||||
// TODO(turbofan): Special treatment for ExternalPointer here,
|
||||
// to avoid incompatible truncations. We really need a story
|
||||
// for the JSFunction::entry field.
|
||||
if (input_type->Is(Type::ExternalPointer())) {
|
||||
(*types)[i] = MachineType::Pointer();
|
||||
} else {
|
||||
MachineRepresentation rep = input_type->IsInhabited()
|
||||
? input_info->representation()
|
||||
: MachineRepresentation::kNone;
|
||||
MachineType machine_type(rep, DeoptValueSemanticOf(input_type));
|
||||
DCHECK(machine_type.representation() !=
|
||||
MachineRepresentation::kWord32 ||
|
||||
machine_type.semantic() == MachineSemantic::kInt32 ||
|
||||
machine_type.semantic() == MachineSemantic::kUint32);
|
||||
(*types)[i] = machine_type;
|
||||
}
|
||||
}
|
||||
NodeProperties::ChangeOp(node,
|
||||
jsgraph_->common()->TypedObjectState(types));
|
||||
@ -1384,6 +1381,14 @@ class RepresentationSelector {
|
||||
return VisitLeaf(node, MachineRepresentation::kTagged);
|
||||
case IrOpcode::kHeapConstant:
|
||||
return VisitLeaf(node, MachineRepresentation::kTaggedPointer);
|
||||
case IrOpcode::kPointerConstant: {
|
||||
VisitLeaf(node, MachineType::PointerRepresentation());
|
||||
if (lower()) {
|
||||
intptr_t const value = OpParameter<intptr_t>(node);
|
||||
DeferReplacement(node, lowering->jsgraph()->IntPtrConstant(value));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case IrOpcode::kBranch:
|
||||
ProcessInput(node, 0, UseInfo::Bool());
|
||||
|
@ -598,15 +598,13 @@ Type* Typer::Visitor::TypeRetain(Node* node) {
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeInt32Constant(Node* node) {
|
||||
double number = OpParameter<int32_t>(node);
|
||||
return Type::Intersect(Type::Range(number, number, zone()),
|
||||
Type::Integral32(), zone());
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Type* Typer::Visitor::TypeInt64Constant(Node* node) {
|
||||
// TODO(rossberg): This actually seems to be a PointerConstant so far...
|
||||
return Type::Internal(); // TODO(rossberg): Add int64 bitset type?
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeRelocatableInt32Constant(Node* node) {
|
||||
@ -624,13 +622,11 @@ Type* Typer::Visitor::TypeFloat32Constant(Node* node) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Type* Typer::Visitor::TypeFloat64Constant(Node* node) {
|
||||
UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Type* Typer::Visitor::TypeNumberConstant(Node* node) {
|
||||
double number = OpParameter<double>(node);
|
||||
return Type::NewConstant(number, zone());
|
||||
@ -640,11 +636,13 @@ Type* Typer::Visitor::TypeHeapConstant(Node* node) {
|
||||
return TypeConstant(OpParameter<Handle<HeapObject>>(node));
|
||||
}
|
||||
|
||||
|
||||
Type* Typer::Visitor::TypeExternalConstant(Node* node) {
|
||||
return Type::Internal();
|
||||
return Type::ExternalPointer();
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypePointerConstant(Node* node) {
|
||||
return Type::ExternalPointer();
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeSelect(Node* node) {
|
||||
return Type::Union(Operand(node, 1), Operand(node, 2), zone());
|
||||
|
@ -123,6 +123,7 @@ namespace compiler {
|
||||
V(Function, 1u << 19) \
|
||||
V(Hole, 1u << 20) \
|
||||
V(OtherInternal, 1u << 21) \
|
||||
V(ExternalPointer, 1u << 22) \
|
||||
\
|
||||
V(Signed31, kUnsigned30 | kNegative31) \
|
||||
V(Signed32, kSigned31 | kOtherUnsigned31 | kOtherSigned32) \
|
||||
@ -160,7 +161,7 @@ namespace compiler {
|
||||
V(StringOrReceiver, kString | kReceiver) \
|
||||
V(Unique, kBoolean | kUniqueName | kNull | kUndefined | \
|
||||
kReceiver) \
|
||||
V(Internal, kHole | kOtherInternal) \
|
||||
V(Internal, kHole | kExternalPointer | kOtherInternal) \
|
||||
V(NonInternal, kPrimitive | kReceiver) \
|
||||
V(NonNumber, kUnique | kString | kInternal) \
|
||||
V(Any, 0xfffffffeu)
|
||||
|
@ -333,40 +333,35 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
CheckTypeIs(node, Type::Any());
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kInt32Constant: // TODO(rossberg): rename Word32Constant?
|
||||
// Constants have no inputs.
|
||||
CHECK_EQ(0, input_count);
|
||||
// Type is a 32 bit integer, signed or unsigned.
|
||||
CheckTypeIs(node, Type::Integral32());
|
||||
break;
|
||||
case IrOpcode::kInt64Constant:
|
||||
// Constants have no inputs.
|
||||
CHECK_EQ(0, input_count);
|
||||
// Type is internal.
|
||||
// TODO(rossberg): Introduce proper Int64 type.
|
||||
CheckTypeIs(node, Type::Internal());
|
||||
break;
|
||||
case IrOpcode::kInt32Constant: // TODO(turbofan): rename Word32Constant?
|
||||
case IrOpcode::kInt64Constant: // TODO(turbofan): rename Word64Constant?
|
||||
case IrOpcode::kFloat32Constant:
|
||||
case IrOpcode::kFloat64Constant:
|
||||
case IrOpcode::kRelocatableInt32Constant:
|
||||
case IrOpcode::kRelocatableInt64Constant:
|
||||
// Constants have no inputs.
|
||||
CHECK_EQ(0, input_count);
|
||||
// Type is empty.
|
||||
CheckNotTyped(node);
|
||||
break;
|
||||
case IrOpcode::kNumberConstant:
|
||||
// Constants have no inputs.
|
||||
CHECK_EQ(0, input_count);
|
||||
// Type is a number.
|
||||
CheckTypeIs(node, Type::Number());
|
||||
break;
|
||||
case IrOpcode::kRelocatableInt32Constant:
|
||||
case IrOpcode::kRelocatableInt64Constant:
|
||||
CHECK_EQ(0, input_count);
|
||||
break;
|
||||
case IrOpcode::kHeapConstant:
|
||||
// Constants have no inputs.
|
||||
CHECK_EQ(0, input_count);
|
||||
// Type is anything.
|
||||
CheckTypeIs(node, Type::Any());
|
||||
break;
|
||||
case IrOpcode::kExternalConstant:
|
||||
case IrOpcode::kPointerConstant:
|
||||
// Constants have no inputs.
|
||||
CHECK_EQ(0, input_count);
|
||||
// Type is considered internal.
|
||||
CheckTypeIs(node, Type::Internal());
|
||||
// Type is an external pointer.
|
||||
CheckTypeIs(node, Type::ExternalPointer());
|
||||
break;
|
||||
case IrOpcode::kOsrValue:
|
||||
// OSR values have a value and a control input.
|
||||
|
@ -169,11 +169,6 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
|
||||
CHECK_EQ(effect, NodeProperties::GetEffectInput(use));
|
||||
}
|
||||
|
||||
void CheckInt32Constant(int32_t expected, Node* result) {
|
||||
CHECK_EQ(IrOpcode::kInt32Constant, result->opcode());
|
||||
CHECK_EQ(expected, OpParameter<int32_t>(result));
|
||||
}
|
||||
|
||||
void CheckNumberConstant(double expected, Node* result) {
|
||||
CHECK_EQ(IrOpcode::kNumberConstant, result->opcode());
|
||||
CHECK_EQ(expected, OpParameter<double>(result));
|
||||
@ -694,7 +689,7 @@ TEST(RemoveToNumberEffects) {
|
||||
JSTypedLoweringTester R;
|
||||
|
||||
Node* effect_use = NULL;
|
||||
Node* zero = R.graph.NewNode(R.common.Int32Constant(0));
|
||||
Node* zero = R.graph.NewNode(R.common.NumberConstant(0));
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Node* p0 = R.Parameter(Type::Number());
|
||||
Node* ton = R.Unop(R.javascript.ToNumber(), p0);
|
||||
|
@ -119,7 +119,7 @@ class EscapeAnalysisTest : public TypedGraphTest {
|
||||
if (!control) {
|
||||
control = control_;
|
||||
}
|
||||
Node* zero = graph()->NewNode(common()->Int32Constant(0));
|
||||
Node* zero = graph()->NewNode(common()->NumberConstant(0));
|
||||
return control_ = graph()->NewNode(common()->Return(), zero, value, effect,
|
||||
control);
|
||||
}
|
||||
|
@ -70,11 +70,6 @@ class JSTypedLoweringTest : public TypedGraphTest {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Matcher<Node*> IsIntPtrConstant(intptr_t value) {
|
||||
return sizeof(value) == 4 ? IsInt32Constant(static_cast<int32_t>(value))
|
||||
: IsInt64Constant(static_cast<int64_t>(value));
|
||||
}
|
||||
|
||||
JSOperatorBuilder* javascript() { return &javascript_; }
|
||||
|
||||
private:
|
||||
@ -569,7 +564,7 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArray) {
|
||||
EXPECT_THAT(
|
||||
r.replacement(),
|
||||
IsLoadBuffer(BufferAccess(type),
|
||||
IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
|
||||
IsPointerConstant(bit_cast<intptr_t>(&backing_store[0])),
|
||||
offset_matcher,
|
||||
IsNumberConstant(array->byte_length()->Number()), effect,
|
||||
control));
|
||||
@ -605,7 +600,7 @@ TEST_F(JSTypedLoweringTest, JSLoadPropertyFromExternalTypedArrayWithSafeKey) {
|
||||
EXPECT_THAT(
|
||||
r.replacement(),
|
||||
IsLoadElement(access,
|
||||
IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
|
||||
IsPointerConstant(bit_cast<intptr_t>(&backing_store[0])),
|
||||
key, effect, control));
|
||||
}
|
||||
}
|
||||
@ -650,11 +645,11 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) {
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(
|
||||
r.replacement(),
|
||||
IsStoreBuffer(BufferAccess(type),
|
||||
IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
|
||||
offset_matcher,
|
||||
IsNumberConstant(array->byte_length()->Number()), value,
|
||||
effect, control));
|
||||
IsStoreBuffer(
|
||||
BufferAccess(type),
|
||||
IsPointerConstant(bit_cast<intptr_t>(&backing_store[0])),
|
||||
offset_matcher, IsNumberConstant(array->byte_length()->Number()),
|
||||
value, effect, control));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -703,11 +698,11 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithConversion) {
|
||||
ASSERT_TRUE(r.Changed());
|
||||
EXPECT_THAT(
|
||||
r.replacement(),
|
||||
IsStoreBuffer(BufferAccess(type),
|
||||
IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
|
||||
offset_matcher,
|
||||
IsNumberConstant(array->byte_length()->Number()),
|
||||
value_matcher, effect_matcher, control_matcher));
|
||||
IsStoreBuffer(
|
||||
BufferAccess(type),
|
||||
IsPointerConstant(bit_cast<intptr_t>(&backing_store[0])),
|
||||
offset_matcher, IsNumberConstant(array->byte_length()->Number()),
|
||||
value_matcher, effect_matcher, control_matcher));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -744,7 +739,7 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithSafeKey) {
|
||||
EXPECT_THAT(
|
||||
r.replacement(),
|
||||
IsStoreElement(
|
||||
access, IsIntPtrConstant(bit_cast<intptr_t>(&backing_store[0])),
|
||||
access, IsPointerConstant(bit_cast<intptr_t>(&backing_store[0])),
|
||||
key, value, effect, control));
|
||||
}
|
||||
}
|
||||
|
@ -1790,6 +1790,10 @@ Matcher<Node*> IsNumberConstant(const Matcher<double>& value_matcher) {
|
||||
new IsConstantMatcher<double>(IrOpcode::kNumberConstant, value_matcher));
|
||||
}
|
||||
|
||||
Matcher<Node*> IsPointerConstant(const Matcher<intptr_t>& value_matcher) {
|
||||
return MakeMatcher(new IsConstantMatcher<intptr_t>(IrOpcode::kPointerConstant,
|
||||
value_matcher));
|
||||
}
|
||||
|
||||
Matcher<Node*> IsSelect(const Matcher<MachineRepresentation>& type_matcher,
|
||||
const Matcher<Node*>& value0_matcher,
|
||||
|
@ -93,6 +93,7 @@ Matcher<Node*> IsFloat64Constant(const Matcher<double>& value_matcher);
|
||||
Matcher<Node*> IsInt32Constant(const Matcher<int32_t>& value_matcher);
|
||||
Matcher<Node*> IsInt64Constant(const Matcher<int64_t>& value_matcher);
|
||||
Matcher<Node*> IsNumberConstant(const Matcher<double>& value_matcher);
|
||||
Matcher<Node*> IsPointerConstant(const Matcher<intptr_t>& value_matcher);
|
||||
Matcher<Node*> IsSelect(const Matcher<MachineRepresentation>& type_matcher,
|
||||
const Matcher<Node*>& value0_matcher,
|
||||
const Matcher<Node*>& value1_matcher,
|
||||
|
@ -373,20 +373,6 @@ TEST_BINARY_MONOTONICITY(Divide)
|
||||
TEST_BINARY_MONOTONICITY(Modulus)
|
||||
#undef TEST_BINARY_MONOTONICITY
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Regression tests
|
||||
|
||||
|
||||
TEST_F(TyperTest, TypeRegressInt32Constant) {
|
||||
int values[] = {-5, 10};
|
||||
for (auto i : values) {
|
||||
Node* c = graph()->NewNode(common()->Int32Constant(i));
|
||||
Type* type = NodeProperties::GetType(c);
|
||||
EXPECT_TRUE(type->Is(NewRange(i, i)));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
Loading…
Reference in New Issue
Block a user