Commit 7dcb6ad3 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Restore basic write barrier elimination.

Restore the basic write barrier elimination that we used to run as part
of the simplified lowering phase (in ChangeLowering actually) before, by
moving the write barrier computation to SimplifiedLowering where we can
still look at types and consider the heap/isolate, and just update the
WriteBarrierKind in the FieldAccess/ElementAccess that we later use when
lowering to a machine Load/Store.

CQ_INCLUDE_TRYBOTS=tryserver.v8:v8_linux64_tsan_rel
R=mstarzinger@chromium.org
BUG=v8:4969,chromium:608636
LOG=n

Review-Url: https://codereview.chromium.org/1938993002
Cr-Commit-Position: refs/heads/master@{#35969}
parent 57f0a521
This diff is collapsed.
...@@ -142,12 +142,6 @@ class AccessBuilder final : public AllStatic { ...@@ -142,12 +142,6 @@ class AccessBuilder final : public AllStatic {
static ElementAccess ForTypedArrayElement(ExternalArrayType type, static ElementAccess ForTypedArrayElement(ExternalArrayType type,
bool is_external); bool is_external);
// ===========================================================================
// Access to global per-isolate variables (based on external reference).
// Provides access to the backing store of a StatsCounter.
static FieldAccess ForStatsCounter();
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessBuilder); DISALLOW_IMPLICIT_CONSTRUCTORS(AccessBuilder);
}; };
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include "src/compiler/machine-operator.h" #include "src/compiler/machine-operator.h"
#include "src/compiler/node-properties.h" #include "src/compiler/node-properties.h"
#include "src/compiler/simplified-operator.h" #include "src/compiler/simplified-operator.h"
#include "src/conversions-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -37,38 +36,6 @@ Reduction ChangeLowering::Reduce(Node* node) { ...@@ -37,38 +36,6 @@ Reduction ChangeLowering::Reduce(Node* node) {
return NoChange(); return NoChange();
} }
namespace {
WriteBarrierKind ComputeWriteBarrierKind(BaseTaggedness base_is_tagged,
MachineRepresentation representation,
Node* value) {
// TODO(bmeurer): Optimize write barriers based on input.
if (base_is_tagged == kTaggedBase &&
representation == MachineRepresentation::kTagged) {
if (value->opcode() == IrOpcode::kHeapConstant) {
return kPointerWriteBarrier;
} else if (value->opcode() == IrOpcode::kNumberConstant) {
double const number_value = OpParameter<double>(value);
if (IsSmiDouble(number_value)) return kNoWriteBarrier;
return kPointerWriteBarrier;
}
return kFullWriteBarrier;
}
return kNoWriteBarrier;
}
WriteBarrierKind ComputeWriteBarrierKind(BaseTaggedness base_is_tagged,
MachineRepresentation representation,
int field_offset, Node* value) {
if (base_is_tagged == kTaggedBase && field_offset == HeapObject::kMapOffset) {
// Write barriers for storing maps are cheaper.
return kMapWriteBarrier;
}
return ComputeWriteBarrierKind(base_is_tagged, representation, value);
}
} // namespace
Reduction ChangeLowering::ReduceLoadField(Node* node) { Reduction ChangeLowering::ReduceLoadField(Node* node) {
const FieldAccess& access = FieldAccessOf(node->op()); const FieldAccess& access = FieldAccessOf(node->op());
Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag()); Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag());
...@@ -79,14 +46,11 @@ Reduction ChangeLowering::ReduceLoadField(Node* node) { ...@@ -79,14 +46,11 @@ Reduction ChangeLowering::ReduceLoadField(Node* node) {
Reduction ChangeLowering::ReduceStoreField(Node* node) { Reduction ChangeLowering::ReduceStoreField(Node* node) {
const FieldAccess& access = FieldAccessOf(node->op()); const FieldAccess& access = FieldAccessOf(node->op());
WriteBarrierKind kind = ComputeWriteBarrierKind(
access.base_is_tagged, access.machine_type.representation(),
access.offset, node->InputAt(1));
Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag()); Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag());
node->InsertInput(graph()->zone(), 1, offset); node->InsertInput(graph()->zone(), 1, offset);
NodeProperties::ChangeOp(node, NodeProperties::ChangeOp(node, machine()->Store(StoreRepresentation(
machine()->Store(StoreRepresentation( access.machine_type.representation(),
access.machine_type.representation(), kind))); access.write_barrier_kind)));
return Changed(node); return Changed(node);
} }
...@@ -124,12 +88,9 @@ Reduction ChangeLowering::ReduceLoadElement(Node* node) { ...@@ -124,12 +88,9 @@ Reduction ChangeLowering::ReduceLoadElement(Node* node) {
Reduction ChangeLowering::ReduceStoreElement(Node* node) { Reduction ChangeLowering::ReduceStoreElement(Node* node) {
const ElementAccess& access = ElementAccessOf(node->op()); const ElementAccess& access = ElementAccessOf(node->op());
node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1)));
NodeProperties::ChangeOp( NodeProperties::ChangeOp(node, machine()->Store(StoreRepresentation(
node, machine()->Store(StoreRepresentation( access.machine_type.representation(),
access.machine_type.representation(), access.write_barrier_kind)));
ComputeWriteBarrierKind(access.base_is_tagged,
access.machine_type.representation(),
node->InputAt(2)))));
return Changed(node); return Changed(node);
} }
......
...@@ -279,8 +279,9 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( ...@@ -279,8 +279,9 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
simplified()->LoadField(AccessBuilder::ForJSObjectProperties()), simplified()->LoadField(AccessBuilder::ForJSObjectProperties()),
this_storage, this_effect, this_control); this_storage, this_effect, this_control);
} }
FieldAccess field_access = {kTaggedBase, field_index.offset(), name, FieldAccess field_access = {
field_type, MachineType::AnyTagged()}; kTaggedBase, field_index.offset(), name,
field_type, MachineType::AnyTagged(), kFullWriteBarrier};
if (access_mode == AccessMode::kLoad) { if (access_mode == AccessMode::kLoad) {
if (field_type->Is(Type::UntaggedFloat64())) { if (field_type->Is(Type::UntaggedFloat64())) {
if (!field_index.is_inobject() || field_index.is_hidden_field() || if (!field_index.is_inobject() || field_index.is_hidden_field() ||
...@@ -723,7 +724,8 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( ...@@ -723,7 +724,8 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
element_type = type_cache_.kSmi; element_type = type_cache_.kSmi;
} }
ElementAccess element_access = {kTaggedBase, FixedArray::kHeaderSize, ElementAccess element_access = {kTaggedBase, FixedArray::kHeaderSize,
element_type, element_machine_type}; element_type, element_machine_type,
kFullWriteBarrier};
// Access the actual element. // Access the actual element.
// TODO(bmeurer): Refactor this into separate methods or even a separate // TODO(bmeurer): Refactor this into separate methods or even a separate
......
...@@ -12,22 +12,6 @@ namespace v8 { ...@@ -12,22 +12,6 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
std::ostream& operator<<(std::ostream& os, WriteBarrierKind kind) {
switch (kind) {
case kNoWriteBarrier:
return os << "NoWriteBarrier";
case kMapWriteBarrier:
return os << "MapWriteBarrier";
case kPointerWriteBarrier:
return os << "PointerWriteBarrier";
case kFullWriteBarrier:
return os << "FullWriteBarrier";
}
UNREACHABLE();
return os;
}
bool operator==(StoreRepresentation lhs, StoreRepresentation rhs) { bool operator==(StoreRepresentation lhs, StoreRepresentation rhs) {
return lhs.representation() == rhs.representation() && return lhs.representation() == rhs.representation() &&
lhs.write_barrier_kind() == rhs.write_barrier_kind(); lhs.write_barrier_kind() == rhs.write_barrier_kind();
......
...@@ -32,16 +32,6 @@ class OptionalOperator final { ...@@ -32,16 +32,6 @@ class OptionalOperator final {
const Operator* const op_; const Operator* const op_;
}; };
// Supported write barrier modes.
enum WriteBarrierKind {
kNoWriteBarrier,
kMapWriteBarrier,
kPointerWriteBarrier,
kFullWriteBarrier
};
std::ostream& operator<<(std::ostream& os, WriteBarrierKind);
// A Load needs a MachineType. // A Load needs a MachineType.
typedef MachineType LoadRepresentation; typedef MachineType LoadRepresentation;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <limits> #include <limits>
#include "src/address-map.h"
#include "src/base/bits.h" #include "src/base/bits.h"
#include "src/code-factory.h" #include "src/code-factory.h"
#include "src/compiler/access-builder.h" #include "src/compiler/access-builder.h"
...@@ -18,6 +19,7 @@ ...@@ -18,6 +19,7 @@
#include "src/compiler/representation-change.h" #include "src/compiler/representation-change.h"
#include "src/compiler/simplified-operator.h" #include "src/compiler/simplified-operator.h"
#include "src/compiler/source-position.h" #include "src/compiler/source-position.h"
#include "src/conversions-inl.h"
#include "src/objects.h" #include "src/objects.h"
#include "src/type-cache.h" #include "src/type-cache.h"
...@@ -709,6 +711,71 @@ class RepresentationSelector { ...@@ -709,6 +711,71 @@ class RepresentationSelector {
return changer_->Float64OperatorFor(node->opcode()); return changer_->Float64OperatorFor(node->opcode());
} }
WriteBarrierKind WriteBarrierKindFor(
BaseTaggedness base_taggedness,
MachineRepresentation field_representation, Type* field_type,
Node* value) {
if (base_taggedness == kTaggedBase &&
field_representation == MachineRepresentation::kTagged) {
Type* value_type = NodeProperties::GetType(value);
if (field_type->Is(Type::TaggedSigned()) ||
value_type->Is(Type::TaggedSigned())) {
// Write barriers are only for stores of heap objects.
return kNoWriteBarrier;
}
if (field_type->Is(Type::BooleanOrNullOrUndefined()) ||
value_type->Is(Type::BooleanOrNullOrUndefined())) {
// Write barriers are not necessary when storing true, false, null or
// undefined, because these special oddballs are always in the root set.
return kNoWriteBarrier;
}
if (value_type->IsConstant() &&
value_type->AsConstant()->Value()->IsHeapObject()) {
Handle<HeapObject> value_object =
Handle<HeapObject>::cast(value_type->AsConstant()->Value());
if (value_object->IsMap()) {
// Write barriers for storing maps are cheaper.
return kMapWriteBarrier;
}
RootIndexMap root_index_map(jsgraph_->isolate());
int root_index = root_index_map.Lookup(*value_object);
if (root_index != RootIndexMap::kInvalidRootIndex &&
jsgraph_->isolate()->heap()->RootIsImmortalImmovable(root_index)) {
// Write barriers are unnecessary for immortal immovable roots.
return kNoWriteBarrier;
}
}
if (field_type->Is(Type::TaggedPointer()) ||
value_type->Is(Type::TaggedPointer())) {
// Write barriers for heap objects are cheaper.
return kPointerWriteBarrier;
}
NumberMatcher m(value);
if (m.HasValue()) {
if (IsSmiDouble(m.Value())) {
// Storing a smi doesn't need a write barrier.
return kNoWriteBarrier;
}
// The NumberConstant will be represented as HeapNumber.
return kPointerWriteBarrier;
}
return kFullWriteBarrier;
}
return kNoWriteBarrier;
}
WriteBarrierKind WriteBarrierKindFor(
BaseTaggedness base_taggedness,
MachineRepresentation field_representation, int field_offset,
Type* field_type, Node* value) {
if (base_taggedness == kTaggedBase &&
field_offset == HeapObject::kMapOffset) {
return kMapWriteBarrier;
}
return WriteBarrierKindFor(base_taggedness, field_representation,
field_type, value);
}
// Dispatching routine for visiting the node {node} with the usage {use}. // Dispatching routine for visiting the node {node} with the usage {use}.
// Depending on the operator, propagate new usage info to the inputs. // Depending on the operator, propagate new usage info to the inputs.
void VisitNode(Node* node, Truncation truncation, void VisitNode(Node* node, Truncation truncation,
...@@ -1136,6 +1203,16 @@ class RepresentationSelector { ...@@ -1136,6 +1203,16 @@ class RepresentationSelector {
access.machine_type.representation())); access.machine_type.representation()));
ProcessRemainingInputs(node, 2); ProcessRemainingInputs(node, 2);
SetOutput(node, MachineRepresentation::kNone); SetOutput(node, MachineRepresentation::kNone);
if (lower()) {
WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
access.base_is_tagged, access.machine_type.representation(),
access.offset, access.type, node->InputAt(1));
if (write_barrier_kind < access.write_barrier_kind) {
access.write_barrier_kind = write_barrier_kind;
NodeProperties::ChangeOp(
node, jsgraph_->simplified()->StoreField(access));
}
}
break; break;
} }
case IrOpcode::kLoadBuffer: { case IrOpcode::kLoadBuffer: {
...@@ -1201,6 +1278,16 @@ class RepresentationSelector { ...@@ -1201,6 +1278,16 @@ class RepresentationSelector {
access.machine_type.representation())); // value access.machine_type.representation())); // value
ProcessRemainingInputs(node, 3); ProcessRemainingInputs(node, 3);
SetOutput(node, MachineRepresentation::kNone); SetOutput(node, MachineRepresentation::kNone);
if (lower()) {
WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
access.base_is_tagged, access.machine_type.representation(),
access.type, node->InputAt(2));
if (write_barrier_kind < access.write_barrier_kind) {
access.write_barrier_kind = write_barrier_kind;
NodeProperties::ChangeOp(
node, jsgraph_->simplified()->StoreElement(access));
}
}
break; break;
} }
case IrOpcode::kObjectIsCallable: case IrOpcode::kObjectIsCallable:
......
...@@ -13,6 +13,10 @@ namespace v8 { ...@@ -13,6 +13,10 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
size_t hash_value(BaseTaggedness base_taggedness) {
return static_cast<uint8_t>(base_taggedness);
}
std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) { std::ostream& operator<<(std::ostream& os, BaseTaggedness base_taggedness) {
switch (base_taggedness) { switch (base_taggedness) {
case kUntaggedBase: case kUntaggedBase:
...@@ -84,6 +88,9 @@ BufferAccess const BufferAccessOf(const Operator* op) { ...@@ -84,6 +88,9 @@ BufferAccess const BufferAccessOf(const Operator* op) {
bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) { bool operator==(FieldAccess const& lhs, FieldAccess const& rhs) {
// On purpose we don't include the write barrier kind here, as this method is
// really only relevant for eliminating loads and they don't care about the
// write barrier mode.
return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset && return lhs.base_is_tagged == rhs.base_is_tagged && lhs.offset == rhs.offset &&
lhs.machine_type == rhs.machine_type; lhs.machine_type == rhs.machine_type;
} }
...@@ -95,6 +102,9 @@ bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) { ...@@ -95,6 +102,9 @@ bool operator!=(FieldAccess const& lhs, FieldAccess const& rhs) {
size_t hash_value(FieldAccess const& access) { size_t hash_value(FieldAccess const& access) {
// On purpose we don't include the write barrier kind here, as this method is
// really only relevant for eliminating loads and they don't care about the
// write barrier mode.
return base::hash_combine(access.base_is_tagged, access.offset, return base::hash_combine(access.base_is_tagged, access.offset,
access.machine_type); access.machine_type);
} }
...@@ -110,12 +120,15 @@ std::ostream& operator<<(std::ostream& os, FieldAccess const& access) { ...@@ -110,12 +120,15 @@ std::ostream& operator<<(std::ostream& os, FieldAccess const& access) {
} }
#endif #endif
access.type->PrintTo(os); access.type->PrintTo(os);
os << ", " << access.machine_type << "]"; os << ", " << access.machine_type << ", " << access.write_barrier_kind << "]";
return os; return os;
} }
bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) { bool operator==(ElementAccess const& lhs, ElementAccess const& rhs) {
// On purpose we don't include the write barrier kind here, as this method is
// really only relevant for eliminating loads and they don't care about the
// write barrier mode.
return lhs.base_is_tagged == rhs.base_is_tagged && return lhs.base_is_tagged == rhs.base_is_tagged &&
lhs.header_size == rhs.header_size && lhs.header_size == rhs.header_size &&
lhs.machine_type == rhs.machine_type; lhs.machine_type == rhs.machine_type;
...@@ -128,6 +141,9 @@ bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) { ...@@ -128,6 +141,9 @@ bool operator!=(ElementAccess const& lhs, ElementAccess const& rhs) {
size_t hash_value(ElementAccess const& access) { size_t hash_value(ElementAccess const& access) {
// On purpose we don't include the write barrier kind here, as this method is
// really only relevant for eliminating loads and they don't care about the
// write barrier mode.
return base::hash_combine(access.base_is_tagged, access.header_size, return base::hash_combine(access.base_is_tagged, access.header_size,
access.machine_type); access.machine_type);
} }
...@@ -136,7 +152,7 @@ size_t hash_value(ElementAccess const& access) { ...@@ -136,7 +152,7 @@ size_t hash_value(ElementAccess const& access) {
std::ostream& operator<<(std::ostream& os, ElementAccess const& access) { std::ostream& operator<<(std::ostream& os, ElementAccess const& access) {
os << access.base_is_tagged << ", " << access.header_size << ", "; os << access.base_is_tagged << ", " << access.header_size << ", ";
access.type->PrintTo(os); access.type->PrintTo(os);
os << ", " << access.machine_type; os << ", " << access.machine_type << ", " << access.write_barrier_kind;
return os; return os;
} }
......
...@@ -25,8 +25,9 @@ namespace compiler { ...@@ -25,8 +25,9 @@ namespace compiler {
class Operator; class Operator;
struct SimplifiedOperatorGlobalCache; struct SimplifiedOperatorGlobalCache;
enum BaseTaggedness : uint8_t { kUntaggedBase, kTaggedBase };
enum BaseTaggedness { kUntaggedBase, kTaggedBase }; size_t hash_value(BaseTaggedness);
std::ostream& operator<<(std::ostream&, BaseTaggedness); std::ostream& operator<<(std::ostream&, BaseTaggedness);
...@@ -63,6 +64,7 @@ struct FieldAccess { ...@@ -63,6 +64,7 @@ struct FieldAccess {
MaybeHandle<Name> name; // debugging only. MaybeHandle<Name> name; // debugging only.
Type* type; // type of the field. Type* type; // type of the field.
MachineType machine_type; // machine type of the field. MachineType machine_type; // machine type of the field.
WriteBarrierKind write_barrier_kind; // write barrier hint.
int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; } int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; }
}; };
...@@ -86,6 +88,7 @@ struct ElementAccess { ...@@ -86,6 +88,7 @@ struct ElementAccess {
int header_size; // size of the header, without tag. int header_size; // size of the header, without tag.
Type* type; // type of the element. Type* type; // type of the element.
MachineType machine_type; // machine type of the element. MachineType machine_type; // machine type of the element.
WriteBarrierKind write_barrier_kind; // write barrier hint.
int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; } int tag() const { return base_is_tagged == kTaggedBase ? kHeapObjectTag : 0; }
}; };
......
...@@ -452,6 +452,33 @@ enum AllocationAlignment { ...@@ -452,6 +452,33 @@ enum AllocationAlignment {
kSimd128Unaligned kSimd128Unaligned
}; };
// Supported write barrier modes.
enum WriteBarrierKind : uint8_t {
kNoWriteBarrier,
kMapWriteBarrier,
kPointerWriteBarrier,
kFullWriteBarrier
};
inline size_t hash_value(WriteBarrierKind kind) {
return static_cast<uint8_t>(kind);
}
inline std::ostream& operator<<(std::ostream& os, WriteBarrierKind kind) {
switch (kind) {
case kNoWriteBarrier:
return os << "NoWriteBarrier";
case kMapWriteBarrier:
return os << "MapWriteBarrier";
case kPointerWriteBarrier:
return os << "PointerWriteBarrier";
case kFullWriteBarrier:
return os << "FullWriteBarrier";
}
UNREACHABLE();
return os;
}
// A flag that indicates whether objects should be pretenured when // A flag that indicates whether objects should be pretenured when
// allocated (allocated directly into the old generation) or not // allocated (allocated directly into the old generation) or not
// (allocated in the young generation if the object size and type // (allocated in the young generation if the object size and type
......
...@@ -1350,7 +1350,7 @@ TEST(LowerStoreField_to_store) { ...@@ -1350,7 +1350,7 @@ TEST(LowerStoreField_to_store) {
StoreRepresentation rep = StoreRepresentationOf(store->op()); StoreRepresentation rep = StoreRepresentationOf(store->op());
if (kMachineReps[i].representation() == MachineRepresentation::kTagged) { if (kMachineReps[i].representation() == MachineRepresentation::kTagged) {
CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
} }
CHECK_EQ(kMachineReps[i].representation(), rep.representation()); CHECK_EQ(kMachineReps[i].representation(), rep.representation());
} }
...@@ -1370,7 +1370,7 @@ TEST(LowerStoreField_to_store) { ...@@ -1370,7 +1370,7 @@ TEST(LowerStoreField_to_store) {
CHECK_EQ(IrOpcode::kStore, store->opcode()); CHECK_EQ(IrOpcode::kStore, store->opcode());
CHECK_EQ(t.p1, store->InputAt(2)); CHECK_EQ(t.p1, store->InputAt(2));
StoreRepresentation rep = StoreRepresentationOf(store->op()); StoreRepresentation rep = StoreRepresentationOf(store->op());
CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
} }
} }
...@@ -1415,7 +1415,7 @@ TEST(LowerStoreElement_to_store) { ...@@ -1415,7 +1415,7 @@ TEST(LowerStoreElement_to_store) {
StoreRepresentation rep = StoreRepresentationOf(store->op()); StoreRepresentation rep = StoreRepresentationOf(store->op());
if (kMachineReps[i].representation() == MachineRepresentation::kTagged) { if (kMachineReps[i].representation() == MachineRepresentation::kTagged) {
CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
} }
CHECK_EQ(kMachineReps[i].representation(), rep.representation()); CHECK_EQ(kMachineReps[i].representation(), rep.representation());
} }
...@@ -1435,7 +1435,7 @@ TEST(LowerStoreElement_to_store) { ...@@ -1435,7 +1435,7 @@ TEST(LowerStoreElement_to_store) {
CHECK_EQ(IrOpcode::kStore, store->opcode()); CHECK_EQ(IrOpcode::kStore, store->opcode());
CHECK_EQ(t.p2, store->InputAt(2)); CHECK_EQ(t.p2, store->InputAt(2));
StoreRepresentation rep = StoreRepresentationOf(store->op()); StoreRepresentation rep = StoreRepresentationOf(store->op());
CHECK_EQ(kFullWriteBarrier, rep.write_barrier_kind()); CHECK_EQ(kNoWriteBarrier, rep.write_barrier_kind());
} }
} }
......
...@@ -1504,10 +1504,12 @@ static void TestIncrementalWriteBarrier(Handle<Map> map, Handle<Map> new_map, ...@@ -1504,10 +1504,12 @@ static void TestIncrementalWriteBarrier(Handle<Map> map, Handle<Map> new_map,
CHECK_EQ(boom_value, obj->RawFastDoublePropertyAt(double_field_index)); CHECK_EQ(boom_value, obj->RawFastDoublePropertyAt(double_field_index));
} }
enum OldToWriteBarrierKind {
enum WriteBarrierKind { OLD_TO_OLD_WRITE_BARRIER, OLD_TO_NEW_WRITE_BARRIER }; OLD_TO_OLD_WRITE_BARRIER,
OLD_TO_NEW_WRITE_BARRIER
};
static void TestWriteBarrierObjectShiftFieldsRight( static void TestWriteBarrierObjectShiftFieldsRight(
WriteBarrierKind write_barrier_kind) { OldToWriteBarrierKind write_barrier_kind) {
CcTest::InitializeVM(); CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate(); Isolate* isolate = CcTest::i_isolate();
v8::HandleScope scope(CcTest::isolate()); v8::HandleScope scope(CcTest::isolate());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment