Commit 117a56b7 authored by gdeepti's avatar gdeepti Committed by Commit bot

Add new relocation type WASM_MEMORY_SIZE_REFERENCE, use relocatable pointers...

Add new relocation type WASM_MEMORY_SIZE_REFERENCE, use relocatable pointers to update wasm memory size references in generated code.
 - Add new RelocInfo mode WASM_MEMORY_SIZE_REFERENCE in the assembler and add relocation information to immediates in compare instructions.
 - Use relocatable constants for MemSize/BoundsCheck in the wasm compiler

R=titzer@chromium.org, yangguo@chromium.org, bradnelson@chromium.org

Review-Url: https://codereview.chromium.org/1921203002
Cr-Commit-Position: refs/heads/master@{#36044}
parent 9f214787
......@@ -71,11 +71,6 @@ Address RelocInfo::target_address() {
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
|| rmode_ == EMBEDDED_OBJECT
......@@ -118,19 +113,6 @@ void RelocInfo::set_target_address(Address target,
}
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, size_t old_size, size_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_));
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
Address updated_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_reference &&
updated_reference < new_base + new_size);
Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
icache_flush_mode);
}
Object* RelocInfo::target_object() {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_));
......
......@@ -255,6 +255,42 @@ bool RelocInfo::IsInConstantPool() {
return Assembler::is_constant_pool_load(pc_);
}
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Assembler::target_address_at(pc_, host_);
}
uint32_t RelocInfo::wasm_memory_size_reference() {
DCHECK(IsWasmMemorySizeReference(rmode_));
return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_) || IsWasmMemorySizeReference(rmode_));
if (IsWasmMemoryReference(rmode_)) {
Address updated_memory_reference;
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
updated_memory_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_memory_reference &&
updated_memory_reference < new_base + new_size);
Assembler::set_target_address_at(
isolate_, pc_, host_, updated_memory_reference, icache_flush_mode);
} else if (IsWasmMemorySizeReference(rmode_)) {
uint32_t updated_size_reference;
DCHECK(wasm_memory_size_reference() <= old_size);
updated_size_reference =
new_size + (wasm_memory_size_reference() - old_size);
DCHECK(updated_size_reference <= new_size);
Assembler::set_target_address_at(
isolate_, pc_, host_, reinterpret_cast<Address>(updated_size_reference),
icache_flush_mode);
} else {
UNREACHABLE();
}
}
// -----------------------------------------------------------------------------
// Implementation of Operand and MemOperand
......
......@@ -41,19 +41,6 @@ void RelocInfo::set_target_address(Address target,
}
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, size_t old_size, size_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_));
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
Address updated_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_reference &&
updated_reference < new_base + new_size);
Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
icache_flush_mode);
}
inline int CPURegister::code() const {
DCHECK(IsValid());
return reg_code;
......@@ -705,11 +692,6 @@ Address RelocInfo::target_address() {
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
|| rmode_ == EMBEDDED_OBJECT
......
......@@ -192,6 +192,41 @@ bool RelocInfo::IsInConstantPool() {
return instr->IsLdrLiteralX();
}
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Memory::Address_at(Assembler::target_pointer_address_at(pc_));
}
uint32_t RelocInfo::wasm_memory_size_reference() {
DCHECK(IsWasmMemorySizeReference(rmode_));
return Memory::uint32_at(Assembler::target_pointer_address_at(pc_));
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_) || IsWasmMemorySizeReference(rmode_));
if (IsWasmMemoryReference(rmode_) && old_base != new_base) {
Address updated_memory_reference;
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
updated_memory_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_memory_reference &&
updated_memory_reference < new_base + new_size);
Assembler::set_target_address_at(
isolate_, pc_, host_, updated_memory_reference, icache_flush_mode);
} else if (IsWasmMemorySizeReference(rmode_)) {
uint32_t updated_size_reference;
DCHECK(wasm_memory_size_reference() <= old_size);
updated_size_reference =
new_size + (wasm_memory_size_reference() - old_size);
DCHECK(updated_size_reference <= new_size);
Memory::uint32_at(Assembler::target_pointer_address_at(pc_)) =
updated_size_reference;
} else {
UNREACHABLE();
}
}
Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, Register reg2,
Register reg3, Register reg4) {
......
......@@ -846,6 +846,8 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
return "generator continuation";
case WASM_MEMORY_REFERENCE:
return "wasm memory reference";
case WASM_MEMORY_SIZE_REFERENCE:
return "wasm memory size reference";
case NUMBER_OF_MODES:
case PC_JUMP:
UNREACHABLE();
......@@ -941,6 +943,7 @@ void RelocInfo::Verify(Isolate* isolate) {
case DEBUG_BREAK_SLOT_AT_TAIL_CALL:
case GENERATOR_CONTINUATION:
case WASM_MEMORY_REFERENCE:
case WASM_MEMORY_SIZE_REFERENCE:
case NONE32:
case NONE64:
break;
......
......@@ -384,9 +384,10 @@ class RelocInfo {
CODE_TARGET_WITH_ID,
DEBUGGER_STATEMENT, // Code target for the debugger statement.
EMBEDDED_OBJECT,
CELL,
// To relocate pointers into the wasm memory embedded in wasm code
WASM_MEMORY_REFERENCE,
WASM_MEMORY_SIZE_REFERENCE,
CELL,
// Everything after runtime_entry (inclusive) is not GC'ed.
RUNTIME_ENTRY,
......@@ -430,7 +431,7 @@ class RelocInfo {
FIRST_REAL_RELOC_MODE = CODE_TARGET,
LAST_REAL_RELOC_MODE = VENEER_POOL,
LAST_CODE_ENUM = DEBUGGER_STATEMENT,
LAST_GCED_ENUM = WASM_MEMORY_REFERENCE,
LAST_GCED_ENUM = WASM_MEMORY_SIZE_REFERENCE,
FIRST_SHAREABLE_RELOC_MODE = CELL,
};
......@@ -521,6 +522,9 @@ class RelocInfo {
static inline bool IsWasmMemoryReference(Mode mode) {
return mode == WASM_MEMORY_REFERENCE;
}
static inline bool IsWasmMemorySizeReference(Mode mode) {
return mode == WASM_MEMORY_SIZE_REFERENCE;
}
static inline int ModeMask(Mode mode) { return 1 << mode; }
// Accessors
......@@ -547,6 +551,12 @@ class RelocInfo {
// constant pool, otherwise the pointer is embedded in the instruction stream.
bool IsInConstantPool();
Address wasm_memory_reference();
uint32_t wasm_memory_size_reference();
void update_wasm_memory_reference(
Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
ICacheFlushMode icache_flush_mode = SKIP_ICACHE_FLUSH);
// this relocation applies to;
// can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
INLINE(Address target_address());
......@@ -581,10 +591,6 @@ class RelocInfo {
ICacheFlushMode icache_flush_mode =
FLUSH_ICACHE_IF_NEEDED));
INLINE(Address wasm_memory_reference());
INLINE(void update_wasm_memory_reference(
Address old_base, Address new_base, size_t old_size, size_t new_size,
ICacheFlushMode icache_flush_mode = SKIP_ICACHE_FLUSH));
// Returns the address of the constant pool entry where the target address
// is held. This should only be called if IsInConstantPool returns true.
INLINE(Address constant_pool_entry_address());
......
......@@ -1520,7 +1520,8 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
destination->IsRegister() ? g.ToRegister(destination) : kScratchReg;
switch (src.type()) {
case Constant::kInt32:
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
__ mov(dst, Operand(src.ToInt32(), src.rmode()));
} else {
__ mov(dst, Operand(src.ToInt32()));
......
......@@ -201,11 +201,16 @@ class Arm64OperandConverter final : public InstructionOperandConverter {
Constant constant = ToConstant(operand);
switch (constant.type()) {
case Constant::kInt32:
return Operand(constant.ToInt32());
if (constant.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
return Operand(constant.ToInt32(), constant.rmode());
} else {
return Operand(constant.ToInt32());
}
case Constant::kInt64:
if (constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
return Operand(constant.ToInt64(), constant.rmode());
} else {
DCHECK(constant.rmode() != RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
return Operand(constant.ToInt64());
}
case Constant::kFloat32:
......
......@@ -149,7 +149,8 @@ std::ostream& operator<<(std::ostream& os, ParameterInfo const& i) {
bool operator==(RelocatablePtrConstantInfo const& lhs,
RelocatablePtrConstantInfo const& rhs) {
return lhs.rmode() == rhs.rmode() && lhs.value() == rhs.value();
return lhs.rmode() == rhs.rmode() && lhs.value() == rhs.value() &&
lhs.type() == rhs.type();
}
bool operator!=(RelocatablePtrConstantInfo const& lhs,
......@@ -158,12 +159,12 @@ bool operator!=(RelocatablePtrConstantInfo const& lhs,
}
size_t hash_value(RelocatablePtrConstantInfo const& p) {
return base::hash_combine(p.value(), p.rmode());
return base::hash_combine(p.value(), p.rmode(), p.type());
}
std::ostream& operator<<(std::ostream& os,
RelocatablePtrConstantInfo const& p) {
return os << p.value() << "|" << p.rmode();
return os << p.value() << "|" << p.rmode() << "|" << p.type();
}
#define CACHED_OP_LIST(V) \
......@@ -703,12 +704,11 @@ const Operator* CommonOperatorBuilder::RelocatableInt32Constant(
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(static_cast<intptr_t>(value), // parameter
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,
......
......@@ -117,15 +117,21 @@ const ParameterInfo& ParameterInfoOf(const Operator* const);
class RelocatablePtrConstantInfo final {
public:
RelocatablePtrConstantInfo(intptr_t value, RelocInfo::Mode rmode)
: value_(value), rmode_(rmode) {}
enum Type { kInt32, kInt64 };
RelocatablePtrConstantInfo(int32_t value, RelocInfo::Mode rmode)
: value_(value), rmode_(rmode), type_(kInt32) {}
RelocatablePtrConstantInfo(int64_t value, RelocInfo::Mode rmode)
: value_(value), rmode_(rmode), type_(kInt64) {}
intptr_t value() const { return value_; }
RelocInfo::Mode rmode() const { return rmode_; }
Type type() const { return type_; }
private:
intptr_t value_;
RelocInfo::Mode rmode_;
Type type_;
};
bool operator==(RelocatablePtrConstantInfo const& lhs,
......
......@@ -66,7 +66,8 @@ class IA32OperandConverter : public InstructionOperandConverter {
Immediate ToImmediate(InstructionOperand* operand) {
Constant constant = ToConstant(operand);
if (constant.type() == Constant::kInt32 &&
constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
(constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
constant.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE)) {
return Immediate(reinterpret_cast<Address>(constant.ToInt32()),
constant.rmode());
}
......
......@@ -504,14 +504,17 @@ 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()) {
Constant::Constant(RelocatablePtrConstantInfo info) {
if (info.type() == RelocatablePtrConstantInfo::kInt32) {
type_ = kInt32;
} else if (info.type() == RelocatablePtrConstantInfo::kInt64) {
type_ = kInt64;
} else {
UNREACHABLE();
}
value_ = info.value();
rmode_ = info.rmode();
}
#endif
Handle<HeapObject> Constant::ToHeapObject() const {
DCHECK_EQ(kHeapObject, type());
......
......@@ -1331,7 +1331,8 @@ class InstructionSequence final : public ZoneObject {
Immediates& immediates() { return immediates_; }
ImmediateOperand AddImmediate(const Constant& constant) {
if (constant.type() == Constant::kInt32) {
if (constant.type() == Constant::kInt32 &&
RelocInfo::IsNone(constant.rmode())) {
return ImmediateOperand(ImmediateOperand::INLINE, constant.ToInt32());
}
int index = static_cast<int>(immediates_.size());
......
......@@ -44,6 +44,10 @@ class X64OperandConverter : public InstructionOperandConverter {
DCHECK_EQ(0, bit_cast<int64_t>(constant.ToFloat64()));
return Immediate(0);
}
if (constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
constant.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
return Immediate(constant.ToInt32(), constant.rmode());
}
return Immediate(constant.ToInt32());
}
......@@ -2150,6 +2154,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
__ movq(dst, src.ToInt64(), src.rmode());
} else {
DCHECK(src.rmode() != RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
__ Set(dst, src.ToInt64());
}
break;
......
......@@ -81,11 +81,6 @@ Address RelocInfo::target_address() {
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Memory::Address_at(pc_);
}
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
|| rmode_ == EMBEDDED_OBJECT
......@@ -119,21 +114,6 @@ void RelocInfo::set_target_address(Address target,
}
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, size_t old_size, size_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_));
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
Address updated_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_reference &&
updated_reference < new_base + new_size);
Memory::Address_at(pc_) = updated_reference;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
Assembler::FlushICache(isolate_, pc_, sizeof(int32_t));
}
}
Object* RelocInfo::target_object() {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
return Memory::Object_at(pc_);
......
......@@ -186,6 +186,42 @@ bool RelocInfo::IsInConstantPool() {
return false;
}
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Memory::Address_at(pc_);
}
uint32_t RelocInfo::wasm_memory_size_reference() {
DCHECK(IsWasmMemorySizeReference(rmode_));
return Memory::uint32_at(pc_);
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_) || IsWasmMemorySizeReference(rmode_));
if (IsWasmMemoryReference(rmode_)) {
Address updated_reference;
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
updated_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_reference &&
updated_reference < new_base + new_size);
Memory::Address_at(pc_) = updated_reference;
} else if (IsWasmMemorySizeReference(rmode_)) {
uint32_t updated_size_reference;
DCHECK(wasm_memory_size_reference() <= old_size);
updated_size_reference =
new_size + (wasm_memory_size_reference() - old_size);
DCHECK(updated_size_reference <= new_size);
Memory::uint32_at(pc_) = updated_size_reference;
} else {
UNREACHABLE();
}
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
Assembler::FlushICache(isolate_, pc_, sizeof(int32_t));
}
}
// -----------------------------------------------------------------------------
// Implementation of Operand
......
......@@ -102,11 +102,6 @@ Address RelocInfo::target_address() {
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) ||
......@@ -156,19 +151,6 @@ void RelocInfo::set_target_address(Address target,
}
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, size_t old_size, size_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_));
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
Address updated_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_reference &&
updated_reference < new_base + new_size);
Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
icache_flush_mode);
}
Address Assembler::target_address_from_return_address(Address pc) {
return pc - kCallTargetAddressOffset;
}
......
......@@ -189,6 +189,42 @@ bool RelocInfo::IsInConstantPool() {
return false;
}
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Assembler::target_address_at(pc_, host_);
}
uint32_t RelocInfo::wasm_memory_size_reference() {
DCHECK(IsWasmMemorySizeReference(rmode_));
return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_) || IsWasmMemorySizeReference(rmode_));
if (IsWasmMemoryReference(rmode_)) {
Address updated_memory_reference;
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
updated_memory_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_memory_reference &&
updated_memory_reference < new_base + new_size);
Assembler::set_target_address_at(
isolate_, pc_, host_, updated_memory_reference, icache_flush_mode);
} else if (IsWasmMemorySizeReference(rmode_)) {
uint32_t updated_size_reference;
DCHECK(wasm_memory_size_reference() <= old_size);
updated_size_reference =
new_size + (wasm_memory_size_reference() - old_size);
DCHECK(updated_size_reference <= new_size);
Assembler::set_target_address_at(
isolate_, pc_, host_, reinterpret_cast<Address>(updated_size_reference),
icache_flush_mode);
} else {
UNREACHABLE();
}
}
// -----------------------------------------------------------------------------
// Implementation of Operand and MemOperand.
......
......@@ -102,11 +102,6 @@ Address RelocInfo::target_address() {
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) ||
......@@ -158,19 +153,6 @@ void RelocInfo::set_target_address(Address target,
}
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, size_t old_size, size_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_));
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
Address updated_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_reference &&
updated_reference < new_base + new_size);
Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
icache_flush_mode);
}
Address Assembler::target_address_from_return_address(Address pc) {
return pc - kCallTargetAddressOffset;
}
......
......@@ -167,6 +167,43 @@ bool RelocInfo::IsInConstantPool() {
return false;
}
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Assembler::target_address_at(pc_, host_);
}
uint32_t RelocInfo::wasm_memory_size_reference() {
DCHECK(IsWasmMemorySizeReference(rmode_));
return static_cast<uint32_t>(
reinterpret_cast<intptr_t>((Assembler::target_address_at(pc_, host_))));
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_) || IsWasmMemorySizeReference(rmode_));
if (IsWasmMemoryReference(rmode_)) {
Address updated_memory_reference;
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
updated_memory_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_memory_reference &&
updated_memory_reference < new_base + new_size);
Assembler::set_target_address_at(
isolate_, pc_, host_, updated_memory_reference, icache_flush_mode);
} else if (IsWasmMemorySizeReference(rmode_)) {
uint32_t updated_size_reference;
DCHECK(wasm_memory_size_reference() <= old_size);
updated_size_reference =
new_size + (wasm_memory_size_reference() - old_size);
DCHECK(updated_size_reference <= new_size);
Assembler::set_target_address_at(
isolate_, pc_, host_, reinterpret_cast<Address>(updated_size_reference),
icache_flush_mode);
} else {
UNREACHABLE();
}
}
// -----------------------------------------------------------------------------
// Implementation of Operand and MemOperand.
......
......@@ -328,11 +328,6 @@ Address RelocInfo::target_address() {
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Memory::Address_at(pc_);
}
Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
|| rmode_ == EMBEDDED_OBJECT
......@@ -370,21 +365,6 @@ void RelocInfo::set_target_address(Address target,
}
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, size_t old_size, size_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_));
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
Address updated_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_reference &&
updated_reference < new_base + new_size);
Memory::Address_at(pc_) = updated_reference;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
Assembler::FlushICache(isolate_, pc_, sizeof(int64_t));
}
}
Object* RelocInfo::target_object() {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
return Memory::Object_at(pc_);
......
......@@ -114,6 +114,45 @@ void CpuFeatures::PrintFeatures() {
CpuFeatures::IsSupported(POPCNT), CpuFeatures::IsSupported(ATOM));
}
// -----------------------------------------------------------------------------
// Implementation of RelocInfo
Address RelocInfo::wasm_memory_reference() {
DCHECK(IsWasmMemoryReference(rmode_));
return Memory::Address_at(pc_);
}
uint32_t RelocInfo::wasm_memory_size_reference() {
DCHECK(IsWasmMemorySizeReference(rmode_));
return Memory::uint32_at(pc_);
}
void RelocInfo::update_wasm_memory_reference(
Address old_base, Address new_base, uint32_t old_size, uint32_t new_size,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmMemoryReference(rmode_) || IsWasmMemorySizeReference(rmode_));
if (IsWasmMemoryReference(rmode_)) {
Address updated_reference;
DCHECK(old_base <= wasm_memory_reference() &&
wasm_memory_reference() < old_base + old_size);
updated_reference = new_base + (wasm_memory_reference() - old_base);
DCHECK(new_base <= updated_reference &&
updated_reference < new_base + new_size);
Memory::Address_at(pc_) = updated_reference;
} else if (IsWasmMemorySizeReference(rmode_)) {
uint32_t updated_size_reference;
DCHECK(wasm_memory_size_reference() <= old_size);
updated_size_reference =
new_size + (wasm_memory_size_reference() - old_size);
DCHECK(updated_size_reference <= new_size);
Memory::uint32_at(pc_) = updated_size_reference;
} else {
UNREACHABLE();
}
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
Assembler::FlushICache(isolate_, pc_, sizeof(int64_t));
}
}
// -----------------------------------------------------------------------------
// Implementation of Operand
......@@ -563,14 +602,17 @@ void Assembler::immediate_arithmetic_op(byte subcode,
if (is_int8(src.value_)) {
emit(0x83);
emit_modrm(subcode, dst);
if (!RelocInfo::IsNone(src.rmode_)) {
RecordRelocInfo(src.rmode_);
}
emit(src.value_);
} else if (dst.is(rax)) {
emit(0x05 | (subcode << 3));
emitl(src.value_);
emit(src);
} else {
emit(0x81);
emit_modrm(subcode, dst);
emitl(src.value_);
emit(src);
}
}
......@@ -583,11 +625,14 @@ void Assembler::immediate_arithmetic_op(byte subcode,
if (is_int8(src.value_)) {
emit(0x83);
emit_operand(subcode, dst);
if (!RelocInfo::IsNone(src.rmode_)) {
RecordRelocInfo(src.rmode_);
}
emit(src.value_);
} else {
emit(0x81);
emit_operand(subcode, dst);
emitl(src.value_);
emit(src);
}
}
......
......@@ -334,6 +334,8 @@ enum RoundingMode {
class Immediate BASE_EMBEDDED {
public:
explicit Immediate(int32_t value) : value_(value) {}
explicit Immediate(int32_t value, RelocInfo::Mode rmode)
: value_(value), rmode_(rmode) {}
explicit Immediate(Smi* value) {
DCHECK(SmiValuesAre31Bits()); // Only available for 31-bit SMI.
value_ = static_cast<int32_t>(reinterpret_cast<intptr_t>(value));
......@@ -341,6 +343,7 @@ class Immediate BASE_EMBEDDED {
private:
int32_t value_;
RelocInfo::Mode rmode_ = RelocInfo::NONE32;
friend class Assembler;
};
......@@ -1758,7 +1761,12 @@ class Assembler : public AssemblerBase {
RelocInfo::Mode rmode,
TypeFeedbackId ast_id = TypeFeedbackId::None());
inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
void emit(Immediate x) { emitl(x.value_); }
void emit(Immediate x) {
if (!RelocInfo::IsNone(x.rmode_)) {
RecordRelocInfo(x.rmode_);
}
emitl(x.value_);
}
// Emits a REX prefix that encodes a 64-bit operand size and
// the top bit of both register codes.
......
......@@ -18,14 +18,16 @@ 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) {
Address new_base, uint32_t old_size,
uint32_t new_size) {
Isolate* isolate = CcTest::i_isolate();
bool modified = false;
int mode_mask = (1 << RelocInfo::WASM_MEMORY_REFERENCE);
int mode_mask = RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (RelocInfo::IsWasmMemoryReference(mode)) {
if (RelocInfo::IsWasmMemoryReference(mode) ||
RelocInfo::IsWasmMemorySizeReference(mode)) {
// Patch addresses with change in memory start address
it.rinfo()->update_wasm_memory_reference(old_base, new_base, old_size,
new_size);
......@@ -143,3 +145,26 @@ TEST(RunLoadStoreRelocationOffset) {
RunLoadStoreRelocationOffset<float>(MachineType::Float32());
RunLoadStoreRelocationOffset<double>(MachineType::Float64());
}
TEST(Uint32LessThanRelocation) {
RawMachineAssemblerTester<uint32_t> m;
RawMachineLabel within_bounds, out_of_bounds;
Node* index = m.Int32Constant(0x200);
Node* limit =
m.RelocatableInt32Constant(0x200, RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
Node* cond = m.AddNode(m.machine()->Uint32LessThan(), index, limit);
m.Branch(cond, &within_bounds, &out_of_bounds);
m.Bind(&within_bounds);
m.Return(m.Int32Constant(0xaced));
m.Bind(&out_of_bounds);
m.Return(m.Int32Constant(0xdeadbeef));
// Check that index is out of bounds with current size
CHECK_EQ(0xdeadbeef, m.Call());
m.GenerateCode();
Handle<Code> code = m.GetCode();
UpdateMemoryReferences(code, reinterpret_cast<Address>(1234),
reinterpret_cast<Address>(1234), 0x200, 0x400);
// Check that after limit is increased, index is within bounds.
CHECK_EQ(0xaced, m.Call());
}
......@@ -23,8 +23,7 @@ using namespace v8::internal::compiler;
static int32_t DummyStaticFunction(Object* result) { return 1; }
TEST(WasmRelocationArm) {
CcTest::InitializeVM();
TEST(WasmRelocationArmMemoryReference) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
v8::internal::byte buffer[4096];
......@@ -77,4 +76,59 @@ TEST(WasmRelocationArm) {
#endif
}
TEST(WasmRelocationArmMemorySizeReference) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
v8::internal::byte buffer[4096];
DummyStaticFunction(NULL);
int32_t size = 512;
Label fail;
Assembler assm(isolate, buffer, sizeof buffer);
__ mov(r0, Operand(size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
__ cmp(r0, Operand(size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
__ b(ne, &fail);
__ mov(pc, Operand(lr));
__ bind(&fail);
__ mov(r0, Operand(0xdeadbeef));
__ mov(pc, Operand(lr));
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
CSignature0<int32_t> csig;
CodeRunner<int32_t> runnable(isolate, code, &csig);
int32_t ret_value = runnable.Call();
CHECK_NE(ret_value, 0xdeadbeef);
#ifdef DEBUG
OFStream os(stdout);
code->Print(os);
::printf("f() = %d\n\n", ret_value);
#endif
size_t diff = 512;
int mode_mask = (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (RelocInfo::IsWasmMemorySizeReference(mode)) {
it.rinfo()->update_wasm_memory_reference(
reinterpret_cast<Address>(1234), reinterpret_cast<Address>(1234),
it.rinfo()->wasm_memory_size_reference(),
it.rinfo()->wasm_memory_size_reference() + diff, SKIP_ICACHE_FLUSH);
}
}
ret_value = runnable.Call();
CHECK_NE(ret_value, 0xdeadbeef);
#ifdef DEBUG
code->Print(os);
::printf("f() = %d\n\n", ret_value);
#endif
}
#undef __
......@@ -24,8 +24,7 @@ using namespace v8::internal::compiler;
static int64_t DummyStaticFunction(Object* result) { return 1; }
TEST(WasmRelocationArm64) {
CcTest::InitializeVM();
TEST(WasmRelocationArm64MemoryReference) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
v8::internal::byte buffer[4096];
......@@ -79,4 +78,61 @@ TEST(WasmRelocationArm64) {
#endif
}
TEST(WasmRelocationArm64MemorySizeReference) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
v8::internal::byte buffer[4096];
DummyStaticFunction(NULL);
Immediate size = Immediate(512, RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
Label fail;
MacroAssembler masm(isolate, buffer, sizeof buffer,
v8::internal::CodeObjectRequired::kYes);
__ Mov(x0, size);
__ Cmp(x0, size);
__ B(ne, &fail);
__ Ret();
__ Bind(&fail);
__ Mov(x0, Immediate(0xdeadbeef));
__ Ret();
CodeDesc desc;
masm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
CSignature0<int64_t> csig;
CodeRunner<int64_t> runnable(isolate, code, &csig);
int64_t ret_value = runnable.Call();
CHECK_NE(ret_value, 0xdeadbeef);
#ifdef DEBUG
OFStream os(stdout);
code->Print(os);
::printf("f() = %ld\n\n", ret_value);
#endif
int32_t diff = 512;
int mode_mask = (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (RelocInfo::IsWasmMemorySizeReference(mode)) {
it.rinfo()->update_wasm_memory_reference(
reinterpret_cast<Address>(0x1234), reinterpret_cast<Address>(0x1234),
it.rinfo()->wasm_memory_size_reference(),
it.rinfo()->wasm_memory_size_reference() + diff, SKIP_ICACHE_FLUSH);
}
}
ret_value = runnable.Call();
CHECK_NE(ret_value, 0xdeadbeef);
#ifdef DEBUG
code->Print(os);
::printf("f() = %ld\n\n", ret_value);
#endif
}
#undef __
......@@ -23,8 +23,7 @@ using namespace v8::internal::compiler;
static int32_t DummyStaticFunction(Object* result) { return 1; }
TEST(WasmRelocationIa32) {
CcTest::InitializeVM();
TEST(WasmRelocationIa32MemoryReference) {
Isolate* isolate = CcTest::i_isolate();
Zone zone(isolate->allocator());
HandleScope scope(isolate);
......@@ -78,7 +77,6 @@ TEST(WasmRelocationIa32) {
CHECK_EQ(ret_value, imm + offset);
#ifdef OBJECT_PRINT
// OFStream os(stdout);
code->Print(os);
begin = code->instruction_start();
end = begin + code->instruction_size();
......@@ -86,4 +84,67 @@ TEST(WasmRelocationIa32) {
#endif
}
TEST(WasmRelocationIa32MemorySizeReference) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
Zone zone(isolate->allocator());
HandleScope scope(isolate);
v8::internal::byte buffer[4096];
Assembler assm(isolate, buffer, sizeof buffer);
DummyStaticFunction(NULL);
int32_t size = 80;
Label fail;
__ mov(eax, Immediate(reinterpret_cast<Address>(size),
RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
__ cmp(eax, Immediate(reinterpret_cast<Address>(size),
RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
__ j(not_equal, &fail);
__ ret(0);
__ bind(&fail);
__ mov(eax, 0xdeadbeef);
__ ret(0);
CSignature0<int32_t> csig;
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
USE(code);
CodeRunner<int32_t> runnable(isolate, code, &csig);
int32_t ret_value = runnable.Call();
CHECK_NE(ret_value, 0xdeadbeef);
#ifdef OBJECT_PRINT
OFStream os(stdout);
code->Print(os);
byte* begin = code->instruction_start();
byte* end = begin + code->instruction_size();
disasm::Disassembler::Disassemble(stdout, begin, end);
#endif
size_t offset = 10;
int mode_mask = (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (RelocInfo::IsWasmMemorySizeReference(mode)) {
it.rinfo()->update_wasm_memory_reference(
reinterpret_cast<Address>(1234), reinterpret_cast<Address>(1234),
it.rinfo()->wasm_memory_size_reference(),
it.rinfo()->wasm_memory_size_reference() + offset, SKIP_ICACHE_FLUSH);
}
}
ret_value = runnable.Call();
CHECK_NE(ret_value, 0xdeadbeef);
#ifdef OBJECT_PRINT
code->Print(os);
begin = code->instruction_start();
end = begin + code->instruction_size();
disasm::Disassembler::Disassemble(stdout, begin, end);
#endif
}
#undef __
......@@ -22,8 +22,7 @@ using namespace v8::internal::compiler;
static int32_t DummyStaticFunction(Object* result) { return 1; }
TEST(WasmRelocationX64movq64) {
CcTest::InitializeVM();
TEST(WasmRelocationX64MemoryReference) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
v8::internal::byte buffer[4096];
......@@ -81,4 +80,63 @@ TEST(WasmRelocationX64movq64) {
#endif
}
TEST(WasmRelocationX64WasmMemorySizeReference) {
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
v8::internal::byte buffer[4096];
Assembler assm(isolate, buffer, sizeof buffer);
DummyStaticFunction(NULL);
int32_t size = 512;
Label fail;
__ movl(rax, Immediate(size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
__ cmpl(rax, Immediate(size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE));
__ j(not_equal, &fail);
__ ret(0);
__ bind(&fail);
__ movl(rax, Immediate(0xdeadbeef));
__ ret(0);
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
USE(code);
CSignature0<int64_t> csig;
CodeRunner<int64_t> runnable(isolate, code, &csig);
int64_t ret_value = runnable.Call();
CHECK_NE(ret_value, 0xdeadbeef);
#ifdef OBJECT_PRINT
OFStream os(stdout);
code->Print(os);
byte* begin = code->instruction_start();
byte* end = begin + code->instruction_size();
disasm::Disassembler::Disassemble(stdout, begin, end);
#endif
int32_t diff = 512;
int mode_mask = (1 << RelocInfo::WASM_MEMORY_SIZE_REFERENCE);
for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (RelocInfo::IsWasmMemorySizeReference(mode)) {
it.rinfo()->update_wasm_memory_reference(
reinterpret_cast<Address>(1234), reinterpret_cast<Address>(1234),
it.rinfo()->wasm_memory_size_reference(),
it.rinfo()->wasm_memory_size_reference() + diff, SKIP_ICACHE_FLUSH);
}
}
ret_value = runnable.Call();
CHECK_NE(ret_value, 0xdeadbeef);
#ifdef OBJECT_PRINT
code->Print(os);
begin = code->instruction_start();
end = begin + code->instruction_size();
disasm::Disassembler::Disassemble(stdout, begin, end);
#endif
}
#undef __
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