From 52148c41c948f4e70778de758fb1a0ae118cecc2 Mon Sep 17 00:00:00 2001 From: gdeepti Date: Tue, 12 Apr 2016 02:05:05 -0700 Subject: [PATCH] [compiler] Add relocatable pointer constants for wasm memory references. Add relocatable pointers for wasm memory references that need to be updated when wasm GrowMemory is used. Code generator changes to accept relocatable constants as immediates. R=titzer@chromium.org, yangguo@chromium.org, bradnelson@chromium.org Committed: https://crrev.com/eb5fe0df64ec0add423b2a1f6fb62d5a33dce2a5 Cr-Commit-Position: refs/heads/master@{#35182} Committed: https://crrev.com/297932a302ce0b73c3618ef9e4eba9d9d241f2b3 Cr-Commit-Position: refs/heads/master@{#35400} Review URL: https://codereview.chromium.org/1759383003 Cr-Commit-Position: refs/heads/master@{#35407} --- src/compiler/arm/code-generator-arm.cc | 6 +- src/compiler/arm64/code-generator-arm64.cc | 6 +- src/compiler/common-node-cache.cc | 2 + src/compiler/common-node-cache.h | 10 ++ src/compiler/common-operator.cc | 36 +++++ src/compiler/common-operator.h | 26 +++- src/compiler/ia32/code-generator-ia32.cc | 5 + .../ia32/instruction-selector-ia32.cc | 2 + src/compiler/instruction-selector-impl.h | 3 + src/compiler/instruction-selector.cc | 2 + src/compiler/instruction.cc | 8 + src/compiler/instruction.h | 8 + src/compiler/js-graph.cc | 22 +++ src/compiler/js-graph.h | 4 + src/compiler/opcodes.h | 20 +-- src/compiler/raw-machine-assembler.cc | 6 + src/compiler/raw-machine-assembler.h | 7 + src/compiler/typer.cc | 8 + src/compiler/verifier.cc | 4 + src/compiler/wasm-compiler.cc | 10 +- src/compiler/x64/code-generator-x64.cc | 20 ++- src/compiler/x64/instruction-selector-x64.cc | 1 + src/x64/assembler-x64.cc | 1 - src/x64/macro-assembler-x64.cc | 9 -- src/x64/macro-assembler-x64.h | 1 - test/cctest/cctest.gyp | 1 + test/cctest/compiler/test-run-wasm-machops.cc | 145 ++++++++++++++++++ test/cctest/test-run-wasm-relocation-x64.cc | 1 + 28 files changed, 341 insertions(+), 33 deletions(-) create mode 100644 test/cctest/compiler/test-run-wasm-machops.cc diff --git a/src/compiler/arm/code-generator-arm.cc b/src/compiler/arm/code-generator-arm.cc index 89321949eb..2022068fd9 100644 --- a/src/compiler/arm/code-generator-arm.cc +++ b/src/compiler/arm/code-generator-arm.cc @@ -1448,7 +1448,11 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, destination->IsRegister() ? g.ToRegister(destination) : kScratchReg; switch (src.type()) { case Constant::kInt32: - __ mov(dst, Operand(src.ToInt32())); + if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) { + __ mov(dst, Operand(src.ToInt32(), src.rmode())); + } else { + __ mov(dst, Operand(src.ToInt32())); + } break; case Constant::kInt64: UNREACHABLE(); diff --git a/src/compiler/arm64/code-generator-arm64.cc b/src/compiler/arm64/code-generator-arm64.cc index 456e7e7608..efb84d1948 100644 --- a/src/compiler/arm64/code-generator-arm64.cc +++ b/src/compiler/arm64/code-generator-arm64.cc @@ -185,7 +185,11 @@ class Arm64OperandConverter final : public InstructionOperandConverter { case Constant::kInt32: return Operand(constant.ToInt32()); case Constant::kInt64: - return Operand(constant.ToInt64()); + if (constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) { + return Operand(constant.ToInt64(), constant.rmode()); + } else { + return Operand(constant.ToInt64()); + } case Constant::kFloat32: return Operand( isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED)); diff --git a/src/compiler/common-node-cache.cc b/src/compiler/common-node-cache.cc index a0ae6e8ad7..8a041f3d4f 100644 --- a/src/compiler/common-node-cache.cc +++ b/src/compiler/common-node-cache.cc @@ -29,6 +29,8 @@ void CommonNodeCache::GetCachedNodes(ZoneVector* nodes) { external_constants_.GetCachedNodes(nodes); number_constants_.GetCachedNodes(nodes); heap_constants_.GetCachedNodes(nodes); + relocatable_int32_constants_.GetCachedNodes(nodes); + relocatable_int64_constants_.GetCachedNodes(nodes); } } // namespace compiler diff --git a/src/compiler/common-node-cache.h b/src/compiler/common-node-cache.h index 720bc1531d..cee0c4e837 100644 --- a/src/compiler/common-node-cache.h +++ b/src/compiler/common-node-cache.h @@ -52,6 +52,14 @@ class CommonNodeCache final { Node** FindHeapConstant(Handle value); + Node** FindRelocatableInt32Constant(int32_t value) { + return relocatable_int32_constants_.Find(zone(), value); + } + + Node** FindRelocatableInt64Constant(int64_t value) { + return relocatable_int64_constants_.Find(zone(), value); + } + // Return all nodes from the cache. void GetCachedNodes(ZoneVector* nodes); @@ -65,6 +73,8 @@ class CommonNodeCache final { IntPtrNodeCache external_constants_; Int64NodeCache number_constants_; IntPtrNodeCache heap_constants_; + Int32NodeCache relocatable_int32_constants_; + Int64NodeCache relocatable_int64_constants_; Zone* const zone_; DISALLOW_COPY_AND_ASSIGN(CommonNodeCache); diff --git a/src/compiler/common-operator.cc b/src/compiler/common-operator.cc index 3bb1b34495..4b26102afe 100644 --- a/src/compiler/common-operator.cc +++ b/src/compiler/common-operator.cc @@ -142,6 +142,25 @@ std::ostream& operator<<(std::ostream& os, ParameterInfo const& i) { return os; } +bool operator==(RelocatablePtrConstantInfo const& lhs, + RelocatablePtrConstantInfo const& rhs) { + return lhs.rmode() == rhs.rmode() && lhs.value() == rhs.value(); +} + +bool operator!=(RelocatablePtrConstantInfo const& lhs, + RelocatablePtrConstantInfo const& rhs) { + return !(lhs == rhs); +} + +size_t hash_value(RelocatablePtrConstantInfo const& p) { + return base::hash_combine(p.value(), p.rmode()); +} + +std::ostream& operator<<(std::ostream& os, + RelocatablePtrConstantInfo const& p) { + return os << p.value() << "|" << p.rmode(); +} + #define CACHED_OP_LIST(V) \ V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1) \ V(DeoptimizeIf, Operator::kFoldable, 2, 1, 1, 0, 0, 1) \ @@ -668,6 +687,23 @@ const Operator* CommonOperatorBuilder::HeapConstant( value); // parameter } +const Operator* CommonOperatorBuilder::RelocatableInt32Constant( + int32_t value, RelocInfo::Mode rmode) { + return new (zone()) Operator1( // -- + IrOpcode::kRelocatableInt32Constant, Operator::kPure, // opcode + "RelocatableInt32Constant", // name + 0, 0, 0, 1, 0, 0, // counts + RelocatablePtrConstantInfo(value, rmode)); // parameter +} + +const Operator* CommonOperatorBuilder::RelocatableInt64Constant( + int64_t value, RelocInfo::Mode rmode) { + return new (zone()) Operator1( // -- + IrOpcode::kRelocatableInt64Constant, Operator::kPure, // opcode + "RelocatableInt64Constant", // name + 0, 0, 0, 1, 0, 0, // counts + RelocatablePtrConstantInfo(value, rmode)); // parameter +} const Operator* CommonOperatorBuilder::Select(MachineRepresentation rep, BranchHint hint) { diff --git a/src/compiler/common-operator.h b/src/compiler/common-operator.h index 7c59f47c34..39646e9845 100644 --- a/src/compiler/common-operator.h +++ b/src/compiler/common-operator.h @@ -5,6 +5,7 @@ #ifndef V8_COMPILER_COMMON_OPERATOR_H_ #define V8_COMPILER_COMMON_OPERATOR_H_ +#include "src/assembler.h" #include "src/compiler/frame-states.h" #include "src/machine-type.h" #include "src/zone-containers.h" @@ -13,7 +14,6 @@ namespace v8 { namespace internal { // Forward declarations. -class ExternalReference; class Type; namespace compiler { @@ -114,6 +114,25 @@ std::ostream& operator<<(std::ostream&, ParameterInfo const&); int ParameterIndexOf(const Operator* const); const ParameterInfo& ParameterInfoOf(const Operator* const); +class RelocatablePtrConstantInfo final { + public: + RelocatablePtrConstantInfo(intptr_t value, RelocInfo::Mode rmode) + : value_(value), rmode_(rmode) {} + + intptr_t value() const { return value_; } + RelocInfo::Mode rmode() const { return rmode_; } + + private: + intptr_t value_; + RelocInfo::Mode rmode_; +}; + +bool operator==(RelocatablePtrConstantInfo const& lhs, + RelocatablePtrConstantInfo const& rhs); +bool operator!=(RelocatablePtrConstantInfo const& lhs, + RelocatablePtrConstantInfo const& rhs); +std::ostream& operator<<(std::ostream&, RelocatablePtrConstantInfo const&); +size_t hash_value(RelocatablePtrConstantInfo const& p); // Interface for building common operators that can be used at any level of IR, // including JavaScript, mid-level, and low-level. @@ -155,6 +174,11 @@ class CommonOperatorBuilder final : public ZoneObject { const Operator* NumberConstant(volatile double); const Operator* HeapConstant(const Handle&); + const Operator* RelocatableInt32Constant(int32_t value, + RelocInfo::Mode rmode); + const Operator* RelocatableInt64Constant(int64_t value, + RelocInfo::Mode rmode); + const Operator* Select(MachineRepresentation, BranchHint = BranchHint::kNone); const Operator* Phi(MachineRepresentation representation, int value_input_count); diff --git a/src/compiler/ia32/code-generator-ia32.cc b/src/compiler/ia32/code-generator-ia32.cc index ee05ad00b6..009421f8cc 100644 --- a/src/compiler/ia32/code-generator-ia32.cc +++ b/src/compiler/ia32/code-generator-ia32.cc @@ -65,6 +65,11 @@ class IA32OperandConverter : public InstructionOperandConverter { Immediate ToImmediate(InstructionOperand* operand) { Constant constant = ToConstant(operand); + if (constant.type() == Constant::kInt32 && + constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) { + return Immediate(reinterpret_cast
(constant.ToInt32()), + constant.rmode()); + } switch (constant.type()) { case Constant::kInt32: return Immediate(constant.ToInt32()); diff --git a/src/compiler/ia32/instruction-selector-ia32.cc b/src/compiler/ia32/instruction-selector-ia32.cc index 5c4acce673..0d5cf4ed48 100644 --- a/src/compiler/ia32/instruction-selector-ia32.cc +++ b/src/compiler/ia32/instruction-selector-ia32.cc @@ -56,6 +56,8 @@ class IA32OperandGenerator final : public OperandGenerator { case IrOpcode::kInt32Constant: case IrOpcode::kNumberConstant: case IrOpcode::kExternalConstant: + case IrOpcode::kRelocatableInt32Constant: + case IrOpcode::kRelocatableInt64Constant: return true; case IrOpcode::kHeapConstant: { // Constants in new space cannot be used as immediates in V8 because diff --git a/src/compiler/instruction-selector-impl.h b/src/compiler/instruction-selector-impl.h index e750aed19a..301612c6f2 100644 --- a/src/compiler/instruction-selector-impl.h +++ b/src/compiler/instruction-selector-impl.h @@ -211,6 +211,9 @@ class OperandGenerator { return Constant(OpParameter(node)); case IrOpcode::kFloat32Constant: return Constant(OpParameter(node)); + case IrOpcode::kRelocatableInt32Constant: + case IrOpcode::kRelocatableInt64Constant: + return Constant(OpParameter(node)); case IrOpcode::kFloat64Constant: case IrOpcode::kNumberConstant: return Constant(OpParameter(node)); diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc index d172ed1858..e4fe3722e6 100644 --- a/src/compiler/instruction-selector.cc +++ b/src/compiler/instruction-selector.cc @@ -879,6 +879,8 @@ void InstructionSelector::VisitNode(Node* node) { case IrOpcode::kInt32Constant: case IrOpcode::kInt64Constant: case IrOpcode::kExternalConstant: + case IrOpcode::kRelocatableInt32Constant: + case IrOpcode::kRelocatableInt64Constant: return VisitConstant(node); case IrOpcode::kFloat32Constant: return MarkAsFloat32(node), VisitConstant(node); diff --git a/src/compiler/instruction.cc b/src/compiler/instruction.cc index c757557a0d..d43d669007 100644 --- a/src/compiler/instruction.cc +++ b/src/compiler/instruction.cc @@ -504,6 +504,14 @@ std::ostream& operator<<(std::ostream& os, Constant::Constant(int32_t v) : type_(kInt32), value_(v) {} +Constant::Constant(RelocatablePtrConstantInfo info) +#ifdef V8_HOST_ARCH_32_BIT + : type_(kInt32), value_(info.value()), rmode_(info.rmode()) { +} +#else + : type_(kInt64), value_(info.value()), rmode_(info.rmode()) { +} +#endif std::ostream& operator<<(std::ostream& os, const Constant& constant) { switch (constant.type()) { diff --git a/src/compiler/instruction.h b/src/compiler/instruction.h index 7f64dce978..bc6a241419 100644 --- a/src/compiler/instruction.h +++ b/src/compiler/instruction.h @@ -947,9 +947,12 @@ class Constant final { explicit Constant(Handle obj) : type_(kHeapObject), value_(bit_cast(obj)) {} explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {} + explicit Constant(RelocatablePtrConstantInfo info); Type type() const { return type_; } + RelocInfo::Mode rmode() const { return rmode_; } + int32_t ToInt32() const { DCHECK(type() == kInt32 || type() == kInt64); const int32_t value = static_cast(value_); @@ -992,6 +995,11 @@ class Constant final { private: Type type_; int64_t value_; +#if V8_TARGET_ARCH_32_BIT + RelocInfo::Mode rmode_ = RelocInfo::NONE32; +#else + RelocInfo::Mode rmode_ = RelocInfo::NONE64; +#endif }; diff --git a/src/compiler/js-graph.cc b/src/compiler/js-graph.cc index 98ca7aa3c3..b5e01cf966 100644 --- a/src/compiler/js-graph.cc +++ b/src/compiler/js-graph.cc @@ -139,6 +139,28 @@ Node* JSGraph::Int64Constant(int64_t value) { return *loc; } +Node* JSGraph::RelocatableInt32Constant(int32_t value, RelocInfo::Mode rmode) { + Node** loc = cache_.FindRelocatableInt32Constant(value); + if (*loc == nullptr) { + *loc = graph()->NewNode(common()->RelocatableInt32Constant(value, rmode)); + } + return *loc; +} + +Node* JSGraph::RelocatableInt64Constant(int64_t value, RelocInfo::Mode rmode) { + Node** loc = cache_.FindRelocatableInt64Constant(value); + if (*loc == nullptr) { + *loc = graph()->NewNode(common()->RelocatableInt64Constant(value, rmode)); + } + return *loc; +} + +Node* JSGraph::RelocatableIntPtrConstant(intptr_t value, + RelocInfo::Mode rmode) { + return kPointerSize == 8 + ? RelocatableInt64Constant(value, rmode) + : RelocatableInt32Constant(static_cast(value), rmode); +} Node* JSGraph::NumberConstant(double value) { Node** loc = cache_.FindNumberConstant(value); diff --git a/src/compiler/js-graph.h b/src/compiler/js-graph.h index 06e8030164..31d9e47819 100644 --- a/src/compiler/js-graph.h +++ b/src/compiler/js-graph.h @@ -96,6 +96,10 @@ class JSGraph : public ZoneObject { return IntPtrConstant(bit_cast(value)); } + Node* RelocatableInt32Constant(int32_t value, RelocInfo::Mode rmode); + Node* RelocatableInt64Constant(int64_t value, RelocInfo::Mode rmode); + Node* RelocatableIntPtrConstant(intptr_t value, RelocInfo::Mode rmode); + // Creates a Float32Constant node, usually canonicalized. Node* Float32Constant(float value); diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h index c8b3671a9e..0d2fc3ffa9 100644 --- a/src/compiler/opcodes.h +++ b/src/compiler/opcodes.h @@ -32,14 +32,16 @@ V(End) // Opcodes for constant operators. -#define CONSTANT_OP_LIST(V) \ - V(Int32Constant) \ - V(Int64Constant) \ - V(Float32Constant) \ - V(Float64Constant) \ - V(ExternalConstant) \ - V(NumberConstant) \ - V(HeapConstant) +#define CONSTANT_OP_LIST(V) \ + V(Int32Constant) \ + V(Int64Constant) \ + V(Float32Constant) \ + V(Float64Constant) \ + V(ExternalConstant) \ + V(NumberConstant) \ + V(HeapConstant) \ + V(RelocatableInt32Constant) \ + V(RelocatableInt64Constant) #define INNER_OP_LIST(V) \ V(Select) \ @@ -399,7 +401,7 @@ class IrOpcode { // Returns true if opcode for constant operator. static bool IsConstantOpcode(Value value) { - return kInt32Constant <= value && value <= kHeapConstant; + return kInt32Constant <= value && value <= kRelocatableInt64Constant; } static bool IsPhiOpcode(Value value) { diff --git a/src/compiler/raw-machine-assembler.cc b/src/compiler/raw-machine-assembler.cc index 728d79af5b..c8d9f4f4e5 100644 --- a/src/compiler/raw-machine-assembler.cc +++ b/src/compiler/raw-machine-assembler.cc @@ -35,6 +35,12 @@ RawMachineAssembler::RawMachineAssembler(Isolate* isolate, Graph* graph, graph->SetEnd(graph->NewNode(common_.End(0))); } +Node* RawMachineAssembler::RelocatableIntPtrConstant(intptr_t value, + RelocInfo::Mode rmode) { + return kPointerSize == 8 + ? RelocatableInt64Constant(value, rmode) + : RelocatableInt32Constant(static_cast(value), rmode); +} Schedule* RawMachineAssembler::Export() { // Compute the correct codegen order. diff --git a/src/compiler/raw-machine-assembler.h b/src/compiler/raw-machine-assembler.h index 33d256ae34..2d4d539ee0 100644 --- a/src/compiler/raw-machine-assembler.h +++ b/src/compiler/raw-machine-assembler.h @@ -76,6 +76,7 @@ class RawMachineAssembler { return kPointerSize == 8 ? Int64Constant(value) : Int32Constant(static_cast(value)); } + Node* RelocatableIntPtrConstant(intptr_t value, RelocInfo::Mode rmode); Node* Int32Constant(int32_t value) { return AddNode(common()->Int32Constant(value)); } @@ -104,6 +105,12 @@ class RawMachineAssembler { Node* ExternalConstant(ExternalReference address) { return AddNode(common()->ExternalConstant(address)); } + Node* RelocatableInt32Constant(int32_t value, RelocInfo::Mode rmode) { + return AddNode(common()->RelocatableInt32Constant(value, rmode)); + } + Node* RelocatableInt64Constant(int64_t value, RelocInfo::Mode rmode) { + return AddNode(common()->RelocatableInt64Constant(value, rmode)); + } Node* Projection(int index, Node* a) { return AddNode(common()->Projection(index), a); diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index 2f784f7af8..71079ae958 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -624,6 +624,14 @@ Type* Typer::Visitor::TypeInt64Constant(Node* node) { return Type::Internal(); // TODO(rossberg): Add int64 bitset type? } +// TODO(gdeepti) : Fix this to do something meaningful. +Type* Typer::Visitor::TypeRelocatableInt32Constant(Node* node) { + return Type::Internal(); +} + +Type* Typer::Visitor::TypeRelocatableInt64Constant(Node* node) { + return Type::Internal(); +} Type* Typer::Visitor::TypeFloat32Constant(Node* node) { return Type::Intersect(Type::Of(OpParameter(node), zone()), diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index 1fe71205da..6eb74367ee 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -345,6 +345,10 @@ void Verifier::Visitor::Check(Node* node) { // Type is a number. CheckUpperIs(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); diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc index 3844893f98..ff80f953eb 100644 --- a/src/compiler/wasm-compiler.cc +++ b/src/compiler/wasm-compiler.cc @@ -2294,13 +2294,15 @@ Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { DCHECK(module_ && module_->instance); if (offset == 0) { if (!mem_buffer_) { - mem_buffer_ = jsgraph()->IntPtrConstant( - reinterpret_cast(module_->instance->mem_start)); + mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( + reinterpret_cast(module_->instance->mem_start), + RelocInfo::WASM_MEMORY_REFERENCE); } return mem_buffer_; } else { - return jsgraph()->IntPtrConstant( - reinterpret_cast(module_->instance->mem_start + offset)); + return jsgraph()->RelocatableIntPtrConstant( + reinterpret_cast(module_->instance->mem_start + offset), + RelocInfo::WASM_MEMORY_REFERENCE); } } diff --git a/src/compiler/x64/code-generator-x64.cc b/src/compiler/x64/code-generator-x64.cc index d9c5d60fb9..30b0f9dce6 100644 --- a/src/compiler/x64/code-generator-x64.cc +++ b/src/compiler/x64/code-generator-x64.cc @@ -2078,17 +2078,25 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, : kScratchRegister; switch (src.type()) { case Constant::kInt32: { - // TODO(dcarney): don't need scratch in this case. - int32_t value = src.ToInt32(); - if (value == 0) { - __ xorl(dst, dst); + if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) { + __ movq(dst, src.ToInt64(), src.rmode()); } else { - __ movl(dst, Immediate(value)); + // TODO(dcarney): don't need scratch in this case. + int32_t value = src.ToInt32(); + if (value == 0) { + __ xorl(dst, dst); + } else { + __ movl(dst, Immediate(value)); + } } break; } case Constant::kInt64: - __ Set(dst, src.ToInt64()); + if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) { + __ movq(dst, src.ToInt64(), src.rmode()); + } else { + __ Set(dst, src.ToInt64()); + } break; case Constant::kFloat32: __ Move(dst, diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc index ea1d48b0cc..dd99e89296 100644 --- a/src/compiler/x64/instruction-selector-x64.cc +++ b/src/compiler/x64/instruction-selector-x64.cc @@ -22,6 +22,7 @@ class X64OperandGenerator final : public OperandGenerator { bool CanBeImmediate(Node* node) { switch (node->opcode()) { case IrOpcode::kInt32Constant: + case IrOpcode::kRelocatableInt32Constant: return true; case IrOpcode::kInt64Constant: { const int64_t value = OpParameter(node); diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index 214b786fed..fef973f2d8 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -1484,7 +1484,6 @@ void Assembler::movq(Register dst, uint64_t value, RelocInfo::Mode rmode) { movq(dst, static_cast(value), rmode); } - // Loads the ip-relative location of the src label into the target location // (as a 32-bit offset sign extended to 64-bit). void Assembler::movl(const Operand& dst, Label* src) { diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 5de65989fe..2c4f02c902 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -1116,15 +1116,6 @@ void MacroAssembler::Set(Register dst, int64_t x) { } } -void MacroAssembler::Set(Register dst, int64_t x, RelocInfo::Mode rmode) { - if (rmode == RelocInfo::WASM_MEMORY_REFERENCE) { - DCHECK(x != 0); - movq(dst, x, rmode); - } else { - DCHECK(RelocInfo::IsNone(rmode)); - } -} - void MacroAssembler::Set(const Operand& dst, intptr_t x) { if (kPointerSize == kInt64Size) { if (is_int32(x)) { diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index 7a7de23fe0..63f452ee7f 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -818,7 +818,6 @@ class MacroAssembler: public Assembler { // Load a register with a long value as efficiently as possible. void Set(Register dst, int64_t x); - void Set(Register dst, int64_t x, RelocInfo::Mode rmode); void Set(const Operand& dst, intptr_t x); void Cvtss2sd(XMMRegister dst, XMMRegister src); diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp index 6c50e9a31a..7669bd1926 100644 --- a/test/cctest/cctest.gyp +++ b/test/cctest/cctest.gyp @@ -84,6 +84,7 @@ 'compiler/test-run-stackcheck.cc', 'compiler/test-run-stubs.cc', 'compiler/test-run-variables.cc', + 'compiler/test-run-wasm-machops.cc', 'compiler/test-simplified-lowering.cc', 'cctest.cc', 'expression-type-collector.cc', diff --git a/test/cctest/compiler/test-run-wasm-machops.cc b/test/cctest/compiler/test-run-wasm-machops.cc new file mode 100644 index 0000000000..29709e981b --- /dev/null +++ b/test/cctest/compiler/test-run-wasm-machops.cc @@ -0,0 +1,145 @@ +// Copyright 2016 the V8 project authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in the +// LICENSE file. + +#include +#include +#include + +#include "src/base/bits.h" +#include "src/base/utils/random-number-generator.h" +#include "src/codegen.h" +#include "test/cctest/cctest.h" +#include "test/cctest/compiler/codegen-tester.h" +#include "test/cctest/compiler/graph-builder-tester.h" +#include "test/cctest/compiler/value-helper.h" + +using namespace v8::internal; +using namespace v8::internal::compiler; + +static void UpdateMemoryReferences(Handle code, Address old_base, + Address new_base, size_t old_size, + size_t new_size) { + Isolate* isolate = CcTest::i_isolate(); + bool modified = false; + int mode_mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE); + for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { + RelocInfo::Mode mode = it.rinfo()->rmode(); + if (RelocInfo::IsWasmMemoryReference(mode)) { + // Patch addresses with change in memory start address + it.rinfo()->update_wasm_memory_reference(old_base, new_base, old_size, + new_size); + modified = true; + } + } + if (modified) { + Assembler::FlushICache(isolate, code->instruction_start(), + code->instruction_size()); + } +} + +template +static void RunLoadStoreRelocation(MachineType rep) { + const int kNumElems = 2; + CType buffer[kNumElems]; + CType new_buffer[kNumElems]; + byte* raw = reinterpret_cast(buffer); + byte* new_raw = reinterpret_cast(new_buffer); + for (size_t i = 0; i < sizeof(buffer); i++) { + raw[i] = static_cast((i + sizeof(CType)) ^ 0xAA); + new_raw[i] = static_cast((i + sizeof(CType)) ^ 0xAA); + } + int32_t OK = 0x29000; + RawMachineAssemblerTester m; + Node* base = m.RelocatableIntPtrConstant(reinterpret_cast(raw), + RelocInfo::WASM_MEMORY_REFERENCE); + Node* base1 = m.RelocatableIntPtrConstant( + reinterpret_cast(raw + sizeof(CType)), + RelocInfo::WASM_MEMORY_REFERENCE); + Node* index = m.Int32Constant(0); + Node* load = m.Load(rep, base, index); + m.Store(rep.representation(), base1, index, load, kNoWriteBarrier); + m.Return(m.Int32Constant(OK)); + CHECK(buffer[0] != buffer[1]); + CHECK_EQ(OK, m.Call()); + CHECK(buffer[0] == buffer[1]); + m.GenerateCode(); + Handle code = m.GetCode(); + UpdateMemoryReferences(code, raw, new_raw, sizeof(buffer), + sizeof(new_buffer)); + CHECK(new_buffer[0] != new_buffer[1]); + CHECK_EQ(OK, m.Call()); + CHECK(new_buffer[0] == new_buffer[1]); +} + +TEST(RunLoadStoreRelocation) { + RunLoadStoreRelocation(MachineType::Int8()); + RunLoadStoreRelocation(MachineType::Uint8()); + RunLoadStoreRelocation(MachineType::Int16()); + RunLoadStoreRelocation(MachineType::Uint16()); + RunLoadStoreRelocation(MachineType::Int32()); + RunLoadStoreRelocation(MachineType::Uint32()); + RunLoadStoreRelocation(MachineType::AnyTagged()); + RunLoadStoreRelocation(MachineType::Float32()); + RunLoadStoreRelocation(MachineType::Float64()); +} + +template +static void RunLoadStoreRelocationOffset(MachineType rep) { + RawMachineAssemblerTester r(MachineType::Int32()); + const int kNumElems = 4; + CType buffer[kNumElems]; + CType new_buffer[kNumElems + 1]; + + for (int32_t x = 0; x < kNumElems; x++) { + int32_t y = kNumElems - x - 1; + // initialize the buffer with raw data. + byte* raw = reinterpret_cast(buffer); + for (size_t i = 0; i < sizeof(buffer); i++) { + raw[i] = static_cast((i + sizeof(buffer)) ^ 0xAA); + } + + RawMachineAssemblerTester m; + int32_t OK = 0x29000 + x; + Node* base = m.RelocatableIntPtrConstant(reinterpret_cast(buffer), + RelocInfo::WASM_MEMORY_REFERENCE); + Node* index0 = m.IntPtrConstant(x * sizeof(buffer[0])); + Node* load = m.Load(rep, base, index0); + Node* index1 = m.IntPtrConstant(y * sizeof(buffer[0])); + m.Store(rep.representation(), base, index1, load, kNoWriteBarrier); + m.Return(m.Int32Constant(OK)); + + CHECK(buffer[x] != buffer[y]); + CHECK_EQ(OK, m.Call()); + CHECK(buffer[x] == buffer[y]); + m.GenerateCode(); + + // Initialize new buffer and set old_buffer to 0 + byte* new_raw = reinterpret_cast(new_buffer); + for (size_t i = 0; i < sizeof(buffer); i++) { + raw[i] = 0; + new_raw[i] = static_cast((i + sizeof(buffer)) ^ 0xAA); + } + + // Perform relocation on generated code + Handle code = m.GetCode(); + UpdateMemoryReferences(code, raw, new_raw, sizeof(buffer), + sizeof(new_buffer)); + + CHECK(new_buffer[x] != new_buffer[y]); + CHECK_EQ(OK, m.Call()); + CHECK(new_buffer[x] == new_buffer[y]); + } +} + +TEST(RunLoadStoreRelocationOffset) { + RunLoadStoreRelocationOffset(MachineType::Int8()); + RunLoadStoreRelocationOffset(MachineType::Uint8()); + RunLoadStoreRelocationOffset(MachineType::Int16()); + RunLoadStoreRelocationOffset(MachineType::Uint16()); + RunLoadStoreRelocationOffset(MachineType::Int32()); + RunLoadStoreRelocationOffset(MachineType::Uint32()); + RunLoadStoreRelocationOffset(MachineType::AnyTagged()); + RunLoadStoreRelocationOffset(MachineType::Float32()); + RunLoadStoreRelocationOffset(MachineType::Float64()); +} diff --git a/test/cctest/test-run-wasm-relocation-x64.cc b/test/cctest/test-run-wasm-relocation-x64.cc index f1b6d96b8c..c665b47562 100644 --- a/test/cctest/test-run-wasm-relocation-x64.cc +++ b/test/cctest/test-run-wasm-relocation-x64.cc @@ -21,6 +21,7 @@ using namespace v8::internal::compiler; #define __ assm. static int32_t DummyStaticFunction(Object* result) { return 1; } + TEST(WasmRelocationX64movq64) { CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate();