[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}
This commit is contained in:
parent
fa2fbcfc2d
commit
52148c41c9
@ -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();
|
||||
|
@ -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));
|
||||
|
@ -29,6 +29,8 @@ void CommonNodeCache::GetCachedNodes(ZoneVector<Node*>* 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
|
||||
|
@ -52,6 +52,14 @@ class CommonNodeCache final {
|
||||
|
||||
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.
|
||||
void GetCachedNodes(ZoneVector<Node*>* 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);
|
||||
|
@ -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<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,
|
||||
BranchHint hint) {
|
||||
|
@ -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<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* Phi(MachineRepresentation representation,
|
||||
int value_input_count);
|
||||
|
@ -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<Address>(constant.ToInt32()),
|
||||
constant.rmode());
|
||||
}
|
||||
switch (constant.type()) {
|
||||
case Constant::kInt32:
|
||||
return Immediate(constant.ToInt32());
|
||||
|
@ -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
|
||||
|
@ -211,6 +211,9 @@ class OperandGenerator {
|
||||
return Constant(OpParameter<int64_t>(node));
|
||||
case IrOpcode::kFloat32Constant:
|
||||
return Constant(OpParameter<float>(node));
|
||||
case IrOpcode::kRelocatableInt32Constant:
|
||||
case IrOpcode::kRelocatableInt64Constant:
|
||||
return Constant(OpParameter<RelocatablePtrConstantInfo>(node));
|
||||
case IrOpcode::kFloat64Constant:
|
||||
case IrOpcode::kNumberConstant:
|
||||
return Constant(OpParameter<double>(node));
|
||||
|
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -947,9 +947,12 @@ class Constant final {
|
||||
explicit Constant(Handle<HeapObject> obj)
|
||||
: type_(kHeapObject), value_(bit_cast<intptr_t>(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<int32_t>(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
|
||||
};
|
||||
|
||||
|
||||
|
@ -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<int>(value), rmode);
|
||||
}
|
||||
|
||||
Node* JSGraph::NumberConstant(double value) {
|
||||
Node** loc = cache_.FindNumberConstant(value);
|
||||
|
@ -96,6 +96,10 @@ class JSGraph : public ZoneObject {
|
||||
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.
|
||||
Node* Float32Constant(float value);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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<int>(value), rmode);
|
||||
}
|
||||
|
||||
Schedule* RawMachineAssembler::Export() {
|
||||
// Compute the correct codegen order.
|
||||
|
@ -76,6 +76,7 @@ class RawMachineAssembler {
|
||||
return kPointerSize == 8 ? Int64Constant(value)
|
||||
: Int32Constant(static_cast<int>(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);
|
||||
|
@ -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<float>(node), zone()),
|
||||
|
@ -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);
|
||||
|
@ -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<uintptr_t>(module_->instance->mem_start));
|
||||
mem_buffer_ = jsgraph()->RelocatableIntPtrConstant(
|
||||
reinterpret_cast<uintptr_t>(module_->instance->mem_start),
|
||||
RelocInfo::WASM_MEMORY_REFERENCE);
|
||||
}
|
||||
return mem_buffer_;
|
||||
} else {
|
||||
return jsgraph()->IntPtrConstant(
|
||||
reinterpret_cast<uintptr_t>(module_->instance->mem_start + offset));
|
||||
return jsgraph()->RelocatableIntPtrConstant(
|
||||
reinterpret_cast<uintptr_t>(module_->instance->mem_start + offset),
|
||||
RelocInfo::WASM_MEMORY_REFERENCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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<int64_t>(node);
|
||||
|
@ -1484,7 +1484,6 @@ void Assembler::movq(Register dst, uint64_t value, RelocInfo::Mode rmode) {
|
||||
movq(dst, static_cast<int64_t>(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) {
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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',
|
||||
|
145
test/cctest/compiler/test-run-wasm-machops.cc
Normal file
145
test/cctest/compiler/test-run-wasm-machops.cc
Normal file
@ -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 <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;
|
||||
#define __ assm.
|
||||
|
||||
static int32_t DummyStaticFunction(Object* result) { return 1; }
|
||||
|
||||
TEST(WasmRelocationX64movq64) {
|
||||
CcTest::InitializeVM();
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
|
Loading…
Reference in New Issue
Block a user