Commit 52148c41 authored by gdeepti's avatar gdeepti Committed by Commit bot

[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}
parent fa2fbcfc
...@@ -1448,7 +1448,11 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, ...@@ -1448,7 +1448,11 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
destination->IsRegister() ? g.ToRegister(destination) : kScratchReg; destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
switch (src.type()) { switch (src.type()) {
case Constant::kInt32: case Constant::kInt32:
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
__ mov(dst, Operand(src.ToInt32(), src.rmode()));
} else {
__ mov(dst, Operand(src.ToInt32())); __ mov(dst, Operand(src.ToInt32()));
}
break; break;
case Constant::kInt64: case Constant::kInt64:
UNREACHABLE(); UNREACHABLE();
......
...@@ -185,7 +185,11 @@ class Arm64OperandConverter final : public InstructionOperandConverter { ...@@ -185,7 +185,11 @@ class Arm64OperandConverter final : public InstructionOperandConverter {
case Constant::kInt32: case Constant::kInt32:
return Operand(constant.ToInt32()); return Operand(constant.ToInt32());
case Constant::kInt64: case Constant::kInt64:
if (constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
return Operand(constant.ToInt64(), constant.rmode());
} else {
return Operand(constant.ToInt64()); return Operand(constant.ToInt64());
}
case Constant::kFloat32: case Constant::kFloat32:
return Operand( return Operand(
isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED)); isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED));
......
...@@ -29,6 +29,8 @@ void CommonNodeCache::GetCachedNodes(ZoneVector<Node*>* nodes) { ...@@ -29,6 +29,8 @@ void CommonNodeCache::GetCachedNodes(ZoneVector<Node*>* nodes) {
external_constants_.GetCachedNodes(nodes); external_constants_.GetCachedNodes(nodes);
number_constants_.GetCachedNodes(nodes); number_constants_.GetCachedNodes(nodes);
heap_constants_.GetCachedNodes(nodes); heap_constants_.GetCachedNodes(nodes);
relocatable_int32_constants_.GetCachedNodes(nodes);
relocatable_int64_constants_.GetCachedNodes(nodes);
} }
} // namespace compiler } // namespace compiler
......
...@@ -52,6 +52,14 @@ class CommonNodeCache final { ...@@ -52,6 +52,14 @@ class CommonNodeCache final {
Node** FindHeapConstant(Handle<HeapObject> value); Node** FindHeapConstant(Handle<HeapObject> 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. // Return all nodes from the cache.
void GetCachedNodes(ZoneVector<Node*>* nodes); void GetCachedNodes(ZoneVector<Node*>* nodes);
...@@ -65,6 +73,8 @@ class CommonNodeCache final { ...@@ -65,6 +73,8 @@ class CommonNodeCache final {
IntPtrNodeCache external_constants_; IntPtrNodeCache external_constants_;
Int64NodeCache number_constants_; Int64NodeCache number_constants_;
IntPtrNodeCache heap_constants_; IntPtrNodeCache heap_constants_;
Int32NodeCache relocatable_int32_constants_;
Int64NodeCache relocatable_int64_constants_;
Zone* const zone_; Zone* const zone_;
DISALLOW_COPY_AND_ASSIGN(CommonNodeCache); DISALLOW_COPY_AND_ASSIGN(CommonNodeCache);
......
...@@ -142,6 +142,25 @@ std::ostream& operator<<(std::ostream& os, ParameterInfo const& i) { ...@@ -142,6 +142,25 @@ std::ostream& operator<<(std::ostream& os, ParameterInfo const& i) {
return os; 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) \ #define CACHED_OP_LIST(V) \
V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1) \ V(Dead, Operator::kFoldable, 0, 0, 0, 1, 1, 1) \
V(DeoptimizeIf, Operator::kFoldable, 2, 1, 1, 0, 0, 1) \ V(DeoptimizeIf, Operator::kFoldable, 2, 1, 1, 0, 0, 1) \
...@@ -668,6 +687,23 @@ const Operator* CommonOperatorBuilder::HeapConstant( ...@@ -668,6 +687,23 @@ const Operator* CommonOperatorBuilder::HeapConstant(
value); // parameter value); // parameter
} }
const Operator* CommonOperatorBuilder::RelocatableInt32Constant(
int32_t value, RelocInfo::Mode rmode) {
return new (zone()) Operator1<RelocatablePtrConstantInfo>( // --
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<RelocatablePtrConstantInfo>( // --
IrOpcode::kRelocatableInt64Constant, Operator::kPure, // opcode
"RelocatableInt64Constant", // name
0, 0, 0, 1, 0, 0, // counts
RelocatablePtrConstantInfo(value, rmode)); // parameter
}
const Operator* CommonOperatorBuilder::Select(MachineRepresentation rep, const Operator* CommonOperatorBuilder::Select(MachineRepresentation rep,
BranchHint hint) { BranchHint hint) {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef V8_COMPILER_COMMON_OPERATOR_H_ #ifndef V8_COMPILER_COMMON_OPERATOR_H_
#define V8_COMPILER_COMMON_OPERATOR_H_ #define V8_COMPILER_COMMON_OPERATOR_H_
#include "src/assembler.h"
#include "src/compiler/frame-states.h" #include "src/compiler/frame-states.h"
#include "src/machine-type.h" #include "src/machine-type.h"
#include "src/zone-containers.h" #include "src/zone-containers.h"
...@@ -13,7 +14,6 @@ namespace v8 { ...@@ -13,7 +14,6 @@ namespace v8 {
namespace internal { namespace internal {
// Forward declarations. // Forward declarations.
class ExternalReference;
class Type; class Type;
namespace compiler { namespace compiler {
...@@ -114,6 +114,25 @@ std::ostream& operator<<(std::ostream&, ParameterInfo const&); ...@@ -114,6 +114,25 @@ std::ostream& operator<<(std::ostream&, ParameterInfo const&);
int ParameterIndexOf(const Operator* const); int ParameterIndexOf(const Operator* const);
const ParameterInfo& ParameterInfoOf(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, // Interface for building common operators that can be used at any level of IR,
// including JavaScript, mid-level, and low-level. // including JavaScript, mid-level, and low-level.
...@@ -155,6 +174,11 @@ class CommonOperatorBuilder final : public ZoneObject { ...@@ -155,6 +174,11 @@ class CommonOperatorBuilder final : public ZoneObject {
const Operator* NumberConstant(volatile double); const Operator* NumberConstant(volatile double);
const Operator* HeapConstant(const Handle<HeapObject>&); const Operator* HeapConstant(const Handle<HeapObject>&);
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* Select(MachineRepresentation, BranchHint = BranchHint::kNone);
const Operator* Phi(MachineRepresentation representation, const Operator* Phi(MachineRepresentation representation,
int value_input_count); int value_input_count);
......
...@@ -65,6 +65,11 @@ class IA32OperandConverter : public InstructionOperandConverter { ...@@ -65,6 +65,11 @@ class IA32OperandConverter : public InstructionOperandConverter {
Immediate ToImmediate(InstructionOperand* operand) { Immediate ToImmediate(InstructionOperand* operand) {
Constant constant = ToConstant(operand); Constant constant = ToConstant(operand);
if (constant.type() == Constant::kInt32 &&
constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
return Immediate(reinterpret_cast<Address>(constant.ToInt32()),
constant.rmode());
}
switch (constant.type()) { switch (constant.type()) {
case Constant::kInt32: case Constant::kInt32:
return Immediate(constant.ToInt32()); return Immediate(constant.ToInt32());
......
...@@ -56,6 +56,8 @@ class IA32OperandGenerator final : public OperandGenerator { ...@@ -56,6 +56,8 @@ class IA32OperandGenerator final : public OperandGenerator {
case IrOpcode::kInt32Constant: case IrOpcode::kInt32Constant:
case IrOpcode::kNumberConstant: case IrOpcode::kNumberConstant:
case IrOpcode::kExternalConstant: case IrOpcode::kExternalConstant:
case IrOpcode::kRelocatableInt32Constant:
case IrOpcode::kRelocatableInt64Constant:
return true; return true;
case IrOpcode::kHeapConstant: { case IrOpcode::kHeapConstant: {
// Constants in new space cannot be used as immediates in V8 because // Constants in new space cannot be used as immediates in V8 because
......
...@@ -211,6 +211,9 @@ class OperandGenerator { ...@@ -211,6 +211,9 @@ class OperandGenerator {
return Constant(OpParameter<int64_t>(node)); return Constant(OpParameter<int64_t>(node));
case IrOpcode::kFloat32Constant: case IrOpcode::kFloat32Constant:
return Constant(OpParameter<float>(node)); return Constant(OpParameter<float>(node));
case IrOpcode::kRelocatableInt32Constant:
case IrOpcode::kRelocatableInt64Constant:
return Constant(OpParameter<RelocatablePtrConstantInfo>(node));
case IrOpcode::kFloat64Constant: case IrOpcode::kFloat64Constant:
case IrOpcode::kNumberConstant: case IrOpcode::kNumberConstant:
return Constant(OpParameter<double>(node)); return Constant(OpParameter<double>(node));
......
...@@ -879,6 +879,8 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -879,6 +879,8 @@ void InstructionSelector::VisitNode(Node* node) {
case IrOpcode::kInt32Constant: case IrOpcode::kInt32Constant:
case IrOpcode::kInt64Constant: case IrOpcode::kInt64Constant:
case IrOpcode::kExternalConstant: case IrOpcode::kExternalConstant:
case IrOpcode::kRelocatableInt32Constant:
case IrOpcode::kRelocatableInt64Constant:
return VisitConstant(node); return VisitConstant(node);
case IrOpcode::kFloat32Constant: case IrOpcode::kFloat32Constant:
return MarkAsFloat32(node), VisitConstant(node); return MarkAsFloat32(node), VisitConstant(node);
......
...@@ -504,6 +504,14 @@ std::ostream& operator<<(std::ostream& os, ...@@ -504,6 +504,14 @@ std::ostream& operator<<(std::ostream& os,
Constant::Constant(int32_t v) : type_(kInt32), value_(v) {} 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) { std::ostream& operator<<(std::ostream& os, const Constant& constant) {
switch (constant.type()) { switch (constant.type()) {
......
...@@ -947,9 +947,12 @@ class Constant final { ...@@ -947,9 +947,12 @@ class Constant final {
explicit Constant(Handle<HeapObject> obj) explicit Constant(Handle<HeapObject> obj)
: type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {} : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {} explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {}
explicit Constant(RelocatablePtrConstantInfo info);
Type type() const { return type_; } Type type() const { return type_; }
RelocInfo::Mode rmode() const { return rmode_; }
int32_t ToInt32() const { int32_t ToInt32() const {
DCHECK(type() == kInt32 || type() == kInt64); DCHECK(type() == kInt32 || type() == kInt64);
const int32_t value = static_cast<int32_t>(value_); const int32_t value = static_cast<int32_t>(value_);
...@@ -992,6 +995,11 @@ class Constant final { ...@@ -992,6 +995,11 @@ class Constant final {
private: private:
Type type_; Type type_;
int64_t value_; int64_t value_;
#if V8_TARGET_ARCH_32_BIT
RelocInfo::Mode rmode_ = RelocInfo::NONE32;
#else
RelocInfo::Mode rmode_ = RelocInfo::NONE64;
#endif
}; };
......
...@@ -139,6 +139,28 @@ Node* JSGraph::Int64Constant(int64_t value) { ...@@ -139,6 +139,28 @@ Node* JSGraph::Int64Constant(int64_t value) {
return *loc; 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<int>(value), rmode);
}
Node* JSGraph::NumberConstant(double value) { Node* JSGraph::NumberConstant(double value) {
Node** loc = cache_.FindNumberConstant(value); Node** loc = cache_.FindNumberConstant(value);
......
...@@ -96,6 +96,10 @@ class JSGraph : public ZoneObject { ...@@ -96,6 +96,10 @@ class JSGraph : public ZoneObject {
return IntPtrConstant(bit_cast<intptr_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);
Node* RelocatableIntPtrConstant(intptr_t value, RelocInfo::Mode rmode);
// Creates a Float32Constant node, usually canonicalized. // Creates a Float32Constant node, usually canonicalized.
Node* Float32Constant(float value); Node* Float32Constant(float value);
......
...@@ -39,7 +39,9 @@ ...@@ -39,7 +39,9 @@
V(Float64Constant) \ V(Float64Constant) \
V(ExternalConstant) \ V(ExternalConstant) \
V(NumberConstant) \ V(NumberConstant) \
V(HeapConstant) V(HeapConstant) \
V(RelocatableInt32Constant) \
V(RelocatableInt64Constant)
#define INNER_OP_LIST(V) \ #define INNER_OP_LIST(V) \
V(Select) \ V(Select) \
...@@ -399,7 +401,7 @@ class IrOpcode { ...@@ -399,7 +401,7 @@ class IrOpcode {
// Returns true if opcode for constant operator. // Returns true if opcode for constant operator.
static bool IsConstantOpcode(Value value) { static bool IsConstantOpcode(Value value) {
return kInt32Constant <= value && value <= kHeapConstant; return kInt32Constant <= value && value <= kRelocatableInt64Constant;
} }
static bool IsPhiOpcode(Value value) { static bool IsPhiOpcode(Value value) {
......
...@@ -35,6 +35,12 @@ RawMachineAssembler::RawMachineAssembler(Isolate* isolate, Graph* graph, ...@@ -35,6 +35,12 @@ RawMachineAssembler::RawMachineAssembler(Isolate* isolate, Graph* graph,
graph->SetEnd(graph->NewNode(common_.End(0))); 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<int>(value), rmode);
}
Schedule* RawMachineAssembler::Export() { Schedule* RawMachineAssembler::Export() {
// Compute the correct codegen order. // Compute the correct codegen order.
......
...@@ -76,6 +76,7 @@ class RawMachineAssembler { ...@@ -76,6 +76,7 @@ class RawMachineAssembler {
return kPointerSize == 8 ? Int64Constant(value) return kPointerSize == 8 ? Int64Constant(value)
: Int32Constant(static_cast<int>(value)); : Int32Constant(static_cast<int>(value));
} }
Node* RelocatableIntPtrConstant(intptr_t value, RelocInfo::Mode rmode);
Node* Int32Constant(int32_t value) { Node* Int32Constant(int32_t value) {
return AddNode(common()->Int32Constant(value)); return AddNode(common()->Int32Constant(value));
} }
...@@ -104,6 +105,12 @@ class RawMachineAssembler { ...@@ -104,6 +105,12 @@ class RawMachineAssembler {
Node* ExternalConstant(ExternalReference address) { Node* ExternalConstant(ExternalReference address) {
return AddNode(common()->ExternalConstant(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) { Node* Projection(int index, Node* a) {
return AddNode(common()->Projection(index), a); return AddNode(common()->Projection(index), a);
......
...@@ -624,6 +624,14 @@ Type* Typer::Visitor::TypeInt64Constant(Node* node) { ...@@ -624,6 +624,14 @@ Type* Typer::Visitor::TypeInt64Constant(Node* node) {
return Type::Internal(); // TODO(rossberg): Add int64 bitset type? 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) { Type* Typer::Visitor::TypeFloat32Constant(Node* node) {
return Type::Intersect(Type::Of(OpParameter<float>(node), zone()), return Type::Intersect(Type::Of(OpParameter<float>(node), zone()),
......
...@@ -345,6 +345,10 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -345,6 +345,10 @@ void Verifier::Visitor::Check(Node* node) {
// Type is a number. // Type is a number.
CheckUpperIs(node, Type::Number()); CheckUpperIs(node, Type::Number());
break; break;
case IrOpcode::kRelocatableInt32Constant:
case IrOpcode::kRelocatableInt64Constant:
CHECK_EQ(0, input_count);
break;
case IrOpcode::kHeapConstant: case IrOpcode::kHeapConstant:
// Constants have no inputs. // Constants have no inputs.
CHECK_EQ(0, input_count); CHECK_EQ(0, input_count);
......
...@@ -2294,13 +2294,15 @@ Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { ...@@ -2294,13 +2294,15 @@ Node* WasmGraphBuilder::MemBuffer(uint32_t offset) {
DCHECK(module_ && module_->instance); DCHECK(module_ && module_->instance);
if (offset == 0) { if (offset == 0) {
if (!mem_buffer_) { if (!mem_buffer_) {
mem_buffer_ = jsgraph()->IntPtrConstant( mem_buffer_ = jsgraph()->RelocatableIntPtrConstant(
reinterpret_cast<uintptr_t>(module_->instance->mem_start)); reinterpret_cast<uintptr_t>(module_->instance->mem_start),
RelocInfo::WASM_MEMORY_REFERENCE);
} }
return mem_buffer_; return mem_buffer_;
} else { } else {
return jsgraph()->IntPtrConstant( return jsgraph()->RelocatableIntPtrConstant(
reinterpret_cast<uintptr_t>(module_->instance->mem_start + offset)); reinterpret_cast<uintptr_t>(module_->instance->mem_start + offset),
RelocInfo::WASM_MEMORY_REFERENCE);
} }
} }
......
...@@ -2078,6 +2078,9 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, ...@@ -2078,6 +2078,9 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
: kScratchRegister; : kScratchRegister;
switch (src.type()) { switch (src.type()) {
case Constant::kInt32: { case Constant::kInt32: {
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
__ movq(dst, src.ToInt64(), src.rmode());
} else {
// TODO(dcarney): don't need scratch in this case. // TODO(dcarney): don't need scratch in this case.
int32_t value = src.ToInt32(); int32_t value = src.ToInt32();
if (value == 0) { if (value == 0) {
...@@ -2085,10 +2088,15 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, ...@@ -2085,10 +2088,15 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
} else { } else {
__ movl(dst, Immediate(value)); __ movl(dst, Immediate(value));
} }
}
break; break;
} }
case Constant::kInt64: case Constant::kInt64:
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
__ movq(dst, src.ToInt64(), src.rmode());
} else {
__ Set(dst, src.ToInt64()); __ Set(dst, src.ToInt64());
}
break; break;
case Constant::kFloat32: case Constant::kFloat32:
__ Move(dst, __ Move(dst,
......
...@@ -22,6 +22,7 @@ class X64OperandGenerator final : public OperandGenerator { ...@@ -22,6 +22,7 @@ class X64OperandGenerator final : public OperandGenerator {
bool CanBeImmediate(Node* node) { bool CanBeImmediate(Node* node) {
switch (node->opcode()) { switch (node->opcode()) {
case IrOpcode::kInt32Constant: case IrOpcode::kInt32Constant:
case IrOpcode::kRelocatableInt32Constant:
return true; return true;
case IrOpcode::kInt64Constant: { case IrOpcode::kInt64Constant: {
const int64_t value = OpParameter<int64_t>(node); const int64_t value = OpParameter<int64_t>(node);
......
...@@ -1484,7 +1484,6 @@ void Assembler::movq(Register dst, uint64_t value, RelocInfo::Mode rmode) { ...@@ -1484,7 +1484,6 @@ void Assembler::movq(Register dst, uint64_t value, RelocInfo::Mode rmode) {
movq(dst, static_cast<int64_t>(value), rmode); movq(dst, static_cast<int64_t>(value), rmode);
} }
// Loads the ip-relative location of the src label into the target location // Loads the ip-relative location of the src label into the target location
// (as a 32-bit offset sign extended to 64-bit). // (as a 32-bit offset sign extended to 64-bit).
void Assembler::movl(const Operand& dst, Label* src) { void Assembler::movl(const Operand& dst, Label* src) {
......
...@@ -1116,15 +1116,6 @@ void MacroAssembler::Set(Register dst, int64_t x) { ...@@ -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) { void MacroAssembler::Set(const Operand& dst, intptr_t x) {
if (kPointerSize == kInt64Size) { if (kPointerSize == kInt64Size) {
if (is_int32(x)) { if (is_int32(x)) {
......
...@@ -818,7 +818,6 @@ class MacroAssembler: public Assembler { ...@@ -818,7 +818,6 @@ class MacroAssembler: public Assembler {
// Load a register with a long value as efficiently as possible. // 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);
void Set(Register dst, int64_t x, RelocInfo::Mode rmode);
void Set(const Operand& dst, intptr_t x); void Set(const Operand& dst, intptr_t x);
void Cvtss2sd(XMMRegister dst, XMMRegister src); void Cvtss2sd(XMMRegister dst, XMMRegister src);
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
'compiler/test-run-stackcheck.cc', 'compiler/test-run-stackcheck.cc',
'compiler/test-run-stubs.cc', 'compiler/test-run-stubs.cc',
'compiler/test-run-variables.cc', 'compiler/test-run-variables.cc',
'compiler/test-run-wasm-machops.cc',
'compiler/test-simplified-lowering.cc', 'compiler/test-simplified-lowering.cc',
'cctest.cc', 'cctest.cc',
'expression-type-collector.cc', 'expression-type-collector.cc',
......
// 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 <cmath>
#include <functional>
#include <limits>
#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> 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 <typename CType>
static void RunLoadStoreRelocation(MachineType rep) {
const int kNumElems = 2;
CType buffer[kNumElems];
CType new_buffer[kNumElems];
byte* raw = reinterpret_cast<byte*>(buffer);
byte* new_raw = reinterpret_cast<byte*>(new_buffer);
for (size_t i = 0; i < sizeof(buffer); i++) {
raw[i] = static_cast<byte>((i + sizeof(CType)) ^ 0xAA);
new_raw[i] = static_cast<byte>((i + sizeof(CType)) ^ 0xAA);
}
int32_t OK = 0x29000;
RawMachineAssemblerTester<uint32_t> m;
Node* base = m.RelocatableIntPtrConstant(reinterpret_cast<intptr_t>(raw),
RelocInfo::WASM_MEMORY_REFERENCE);
Node* base1 = m.RelocatableIntPtrConstant(
reinterpret_cast<intptr_t>(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> 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<int8_t>(MachineType::Int8());
RunLoadStoreRelocation<uint8_t>(MachineType::Uint8());
RunLoadStoreRelocation<int16_t>(MachineType::Int16());
RunLoadStoreRelocation<uint16_t>(MachineType::Uint16());
RunLoadStoreRelocation<int32_t>(MachineType::Int32());
RunLoadStoreRelocation<uint32_t>(MachineType::Uint32());
RunLoadStoreRelocation<void*>(MachineType::AnyTagged());
RunLoadStoreRelocation<float>(MachineType::Float32());
RunLoadStoreRelocation<double>(MachineType::Float64());
}
template <typename CType>
static void RunLoadStoreRelocationOffset(MachineType rep) {
RawMachineAssemblerTester<int32_t> 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<byte*>(buffer);
for (size_t i = 0; i < sizeof(buffer); i++) {
raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
}
RawMachineAssemblerTester<int32_t> m;
int32_t OK = 0x29000 + x;
Node* base = m.RelocatableIntPtrConstant(reinterpret_cast<intptr_t>(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<byte*>(new_buffer);
for (size_t i = 0; i < sizeof(buffer); i++) {
raw[i] = 0;
new_raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
}
// Perform relocation on generated code
Handle<Code> 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<int8_t>(MachineType::Int8());
RunLoadStoreRelocationOffset<uint8_t>(MachineType::Uint8());
RunLoadStoreRelocationOffset<int16_t>(MachineType::Int16());
RunLoadStoreRelocationOffset<uint16_t>(MachineType::Uint16());
RunLoadStoreRelocationOffset<int32_t>(MachineType::Int32());
RunLoadStoreRelocationOffset<uint32_t>(MachineType::Uint32());
RunLoadStoreRelocationOffset<void*>(MachineType::AnyTagged());
RunLoadStoreRelocationOffset<float>(MachineType::Float32());
RunLoadStoreRelocationOffset<double>(MachineType::Float64());
}
...@@ -21,6 +21,7 @@ using namespace v8::internal::compiler; ...@@ -21,6 +21,7 @@ using namespace v8::internal::compiler;
#define __ assm. #define __ assm.
static int32_t DummyStaticFunction(Object* result) { return 1; } static int32_t DummyStaticFunction(Object* result) { return 1; }
TEST(WasmRelocationX64movq64) { TEST(WasmRelocationX64movq64) {
CcTest::InitializeVM(); CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate(); Isolate* isolate = CcTest::i_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