From cc815b69c17da368107ed77306a5bb161170c834 Mon Sep 17 00:00:00 2001 From: gdeepti Date: Wed, 16 Mar 2016 10:10:04 -0700 Subject: [PATCH] Assembler changes for enabling GrowHeap in Wasm - New RelocInfo mode WASM_MEMORY_REFERENCE as a marker for wasm code objects that need to be relocated on a heap change - RelocInfo mode recorded for immediates that use the memory buffer as base - Tests to verify address patching works BUG= Review URL: https://codereview.chromium.org/1759873002 Cr-Commit-Position: refs/heads/master@{#34831} --- src/arm/assembler-arm-inl.h | 16 ++++ src/arm64/assembler-arm64-inl.h | 16 ++++ src/arm64/assembler-arm64.cc | 3 +- src/assembler.cc | 3 + src/assembler.h | 12 ++- src/ia32/assembler-ia32-inl.h | 22 +++++ src/ia32/assembler-ia32.h | 1 + src/mips/assembler-mips-inl.h | 16 ++++ src/mips64/assembler-mips64-inl.h | 16 ++++ src/x64/assembler-x64-inl.h | 18 ++++ src/x64/assembler-x64.cc | 11 +-- src/x64/assembler-x64.h | 6 +- src/x64/macro-assembler-x64.cc | 8 ++ src/x64/macro-assembler-x64.h | 1 + test/cctest/cctest.gyp | 12 ++- test/cctest/test-run-wasm-relocation-arm.cc | 80 +++++++++++++++++ test/cctest/test-run-wasm-relocation-arm64.cc | 82 +++++++++++++++++ test/cctest/test-run-wasm-relocation-ia32.cc | 89 +++++++++++++++++++ test/cctest/test-run-wasm-relocation-x64.cc | 84 +++++++++++++++++ 19 files changed, 483 insertions(+), 13 deletions(-) create mode 100644 test/cctest/test-run-wasm-relocation-arm.cc create mode 100644 test/cctest/test-run-wasm-relocation-arm64.cc create mode 100644 test/cctest/test-run-wasm-relocation-ia32.cc create mode 100644 test/cctest/test-run-wasm-relocation-x64.cc diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h index 0de96428f3..b0b22b63c2 100644 --- a/src/arm/assembler-arm-inl.h +++ b/src/arm/assembler-arm-inl.h @@ -71,6 +71,10 @@ 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_) @@ -114,6 +118,18 @@ 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); diff --git a/src/arm64/assembler-arm64-inl.h b/src/arm64/assembler-arm64-inl.h index aeca563c37..6191216281 100644 --- a/src/arm64/assembler-arm64-inl.h +++ b/src/arm64/assembler-arm64-inl.h @@ -41,6 +41,18 @@ 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()); @@ -693,6 +705,10 @@ 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_) diff --git a/src/arm64/assembler-arm64.cc b/src/arm64/assembler-arm64.cc index ea7a732f8a..d837c64994 100644 --- a/src/arm64/assembler-arm64.cc +++ b/src/arm64/assembler-arm64.cc @@ -437,7 +437,8 @@ bool ConstPool::CanBeShared(RelocInfo::Mode mode) { DCHECK(mode != RelocInfo::NONE32); return RelocInfo::IsNone(mode) || - (!assm_->serializer_enabled() && (mode >= RelocInfo::CELL)); + (!assm_->serializer_enabled() && + (mode >= RelocInfo::FIRST_SHAREABLE_RELOC_MODE)); } diff --git a/src/assembler.cc b/src/assembler.cc index d0bba286e6..2f0b880597 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -842,6 +842,8 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) { return "code age sequence"; case GENERATOR_CONTINUATION: return "generator continuation"; + case WASM_MEMORY_REFERENCE: + return "wasm memory reference"; case NUMBER_OF_MODES: case PC_JUMP: UNREACHABLE(); @@ -935,6 +937,7 @@ void RelocInfo::Verify(Isolate* isolate) { case DEBUG_BREAK_SLOT_AT_RETURN: case DEBUG_BREAK_SLOT_AT_CALL: case GENERATOR_CONTINUATION: + case WASM_MEMORY_REFERENCE: case NONE32: case NONE64: break; diff --git a/src/assembler.h b/src/assembler.h index 84c3fdcc3f..b6c48cf46f 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -385,6 +385,8 @@ class RelocInfo { 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, // Everything after runtime_entry (inclusive) is not GC'ed. RUNTIME_ENTRY, @@ -427,7 +429,8 @@ class RelocInfo { FIRST_REAL_RELOC_MODE = CODE_TARGET, LAST_REAL_RELOC_MODE = VENEER_POOL, LAST_CODE_ENUM = DEBUGGER_STATEMENT, - LAST_GCED_ENUM = CELL, + LAST_GCED_ENUM = WASM_MEMORY_REFERENCE, + FIRST_SHAREABLE_RELOC_MODE = CELL, }; STATIC_ASSERT(NUMBER_OF_MODES <= kBitsPerInt); @@ -511,6 +514,9 @@ class RelocInfo { static inline bool IsGeneratorContinuation(Mode mode) { return mode == GENERATOR_CONTINUATION; } + static inline bool IsWasmMemoryReference(Mode mode) { + return mode == WASM_MEMORY_REFERENCE; + } static inline int ModeMask(Mode mode) { return 1 << mode; } // Accessors @@ -571,6 +577,10 @@ 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()); diff --git a/src/ia32/assembler-ia32-inl.h b/src/ia32/assembler-ia32-inl.h index 4ad8ec6d2a..cd09e928df 100644 --- a/src/ia32/assembler-ia32-inl.h +++ b/src/ia32/assembler-ia32-inl.h @@ -81,6 +81,10 @@ 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_) @@ -115,6 +119,20 @@ 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); @@ -321,6 +339,10 @@ Immediate::Immediate(int x) { rmode_ = RelocInfo::NONE32; } +Immediate::Immediate(Address x, RelocInfo::Mode rmode) { + x_ = reinterpret_cast(x); + rmode_ = rmode; +} Immediate::Immediate(const ExternalReference& ext) { x_ = reinterpret_cast(ext.address()); diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h index 57179dd168..723a1cd431 100644 --- a/src/ia32/assembler-ia32.h +++ b/src/ia32/assembler-ia32.h @@ -271,6 +271,7 @@ class Immediate BASE_EMBEDDED { inline explicit Immediate(Handle handle); inline explicit Immediate(Smi* value); inline explicit Immediate(Address addr); + inline explicit Immediate(Address x, RelocInfo::Mode rmode); static Immediate CodeRelativeOffset(Label* label) { return Immediate(label); diff --git a/src/mips/assembler-mips-inl.h b/src/mips/assembler-mips-inl.h index 703f3ce5d6..517d4adab0 100644 --- a/src/mips/assembler-mips-inl.h +++ b/src/mips/assembler-mips-inl.h @@ -102,6 +102,10 @@ 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_) || @@ -152,6 +156,18 @@ 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; diff --git a/src/mips64/assembler-mips64-inl.h b/src/mips64/assembler-mips64-inl.h index 37ee3a6807..dec58e895c 100644 --- a/src/mips64/assembler-mips64-inl.h +++ b/src/mips64/assembler-mips64-inl.h @@ -102,6 +102,10 @@ 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_) || @@ -154,6 +158,18 @@ 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; diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h index 4e0370ad5f..f32f407a8d 100644 --- a/src/x64/assembler-x64-inl.h +++ b/src/x64/assembler-x64-inl.h @@ -326,6 +326,10 @@ 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_) @@ -364,6 +368,20 @@ 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); diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index 3cf3398e87..75df415afd 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -1469,17 +1469,18 @@ void Assembler::movp(Register dst, void* value, RelocInfo::Mode rmode) { emitp(value, rmode); } - -void Assembler::movq(Register dst, int64_t value) { +void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) { EnsureSpace ensure_space(this); emit_rex_64(dst); emit(0xB8 | dst.low_bits()); + if (!RelocInfo::IsNone(rmode)) { + RecordRelocInfo(rmode, value); + } emitq(value); } - -void Assembler::movq(Register dst, uint64_t value) { - movq(dst, static_cast(value)); +void Assembler::movq(Register dst, uint64_t value, RelocInfo::Mode rmode) { + movq(dst, static_cast(value), rmode); } diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index 0ce714db09..844fa50614 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -699,8 +699,10 @@ class Assembler : public AssemblerBase { void movp(Register dst, void* ptr, RelocInfo::Mode rmode); // Loads a 64-bit immediate into a register. - void movq(Register dst, int64_t value); - void movq(Register dst, uint64_t value); + void movq(Register dst, int64_t value, + RelocInfo::Mode rmode = RelocInfo::NONE64); + void movq(Register dst, uint64_t value, + RelocInfo::Mode rmode = RelocInfo::NONE64); void movsxbl(Register dst, Register src); void movsxbl(Register dst, const Operand& src); diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 81017b39e1..fa6c710c27 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -1114,6 +1114,14 @@ 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) { diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index b1990bac03..039ad8c5c1 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -818,6 +818,7 @@ class MacroAssembler: public Assembler { // Load a register with a long value as efficiently as possible. void Set(Register dst, int64_t x); + void Set(Register dst, int64_t x, RelocInfo::Mode rmode); void Set(const Operand& dst, intptr_t x); void Cvtss2sd(XMMRegister dst, XMMRegister src); diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp index 26a671e962..680920fc61 100644 --- a/test/cctest/cctest.gyp +++ b/test/cctest/cctest.gyp @@ -202,7 +202,8 @@ 'test-code-stubs-ia32.cc', 'test-disasm-ia32.cc', 'test-macro-assembler-ia32.cc', - 'test-log-stack-tracer.cc' + 'test-log-stack-tracer.cc', + 'test-run-wasm-relocation-ia32.cc' ], }], ['v8_target_arch=="x64"', { @@ -212,7 +213,8 @@ 'test-code-stubs-x64.cc', 'test-disasm-x64.cc', 'test-macro-assembler-x64.cc', - 'test-log-stack-tracer.cc' + 'test-log-stack-tracer.cc', + 'test-run-wasm-relocation-x64.cc' ], }], ['v8_target_arch=="arm"', { @@ -221,7 +223,8 @@ 'test-code-stubs.cc', 'test-code-stubs-arm.cc', 'test-disasm-arm.cc', - 'test-macro-assembler-arm.cc' + 'test-macro-assembler-arm.cc', + 'test-run-wasm-relocation-arm.cc' ], }], ['v8_target_arch=="arm64"', { @@ -233,7 +236,8 @@ 'test-disasm-arm64.cc', 'test-fuzz-arm64.cc', 'test-javascript-arm64.cc', - 'test-js-arm64-variables.cc' + 'test-js-arm64-variables.cc', + 'test-run-wasm-relocation-arm64.cc' ], }], ['v8_target_arch=="s390"', { diff --git a/test/cctest/test-run-wasm-relocation-arm.cc b/test/cctest/test-run-wasm-relocation-arm.cc new file mode 100644 index 0000000000..adfeb28b2f --- /dev/null +++ b/test/cctest/test-run-wasm-relocation-arm.cc @@ -0,0 +1,80 @@ +// Copyright 2015 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 // NOLINT(readability/streams) + +#include "src/v8.h" +#include "test/cctest/cctest.h" + +#include "src/arm/assembler-arm-inl.h" +#include "src/arm/simulator-arm.h" +#include "src/disassembler.h" +#include "src/factory.h" +#include "src/ostreams.h" +#include "test/cctest/compiler/c-signature.h" +#include "test/cctest/compiler/call-tester.h" + +using namespace v8::base; +using namespace v8::internal; +using namespace v8::internal::compiler; + +#define __ assm. + +static int32_t DummyStaticFunction(Object* result) { return 1; } + +TEST(WasmRelocationArm) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + v8::internal::byte buffer[4096]; + DummyStaticFunction(NULL); + int32_t imm = 1234567; + + Assembler assm(isolate, buffer, sizeof buffer); + + __ mov(r0, Operand(imm, RelocInfo::WASM_MEMORY_REFERENCE)); + __ mov(pc, Operand(lr)); + + CodeDesc desc; + assm.GetCode(&desc); + Handle code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle()); + + CSignature0 csig; + CodeRunner runnable(isolate, code, &csig); + int32_t ret_value = runnable.Call(); + CHECK_EQ(ret_value, imm); + +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); + ::printf("f() = %d\n\n", ret_value); +#endif + size_t offset = 1234; + + // Relocating references by offset + 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)) { + // Dummy values of size used here as the objective of the test is to + // verify that the immediate is patched correctly + it.rinfo()->update_wasm_memory_reference( + it.rinfo()->wasm_memory_reference(), + it.rinfo()->wasm_memory_reference() + offset, 1, 2, + SKIP_ICACHE_FLUSH); + } + } + + // Call into relocated code object + ret_value = runnable.Call(); + CHECK_EQ((imm + offset), ret_value); + +#ifdef DEBUG + code->Print(os); + ::printf("f() = %d\n\n", ret_value); +#endif +} + +#undef __ diff --git a/test/cctest/test-run-wasm-relocation-arm64.cc b/test/cctest/test-run-wasm-relocation-arm64.cc new file mode 100644 index 0000000000..48f9e85ba1 --- /dev/null +++ b/test/cctest/test-run-wasm-relocation-arm64.cc @@ -0,0 +1,82 @@ +// Copyright 2015 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 // NOLINT(readability/streams) + +#include "src/v8.h" +#include "test/cctest/cctest.h" + +#include "src/arm64/simulator-arm64.h" +#include "src/arm64/utils-arm64.h" +#include "src/disassembler.h" +#include "src/factory.h" +#include "src/macro-assembler.h" +#include "src/ostreams.h" +#include "test/cctest/compiler/c-signature.h" +#include "test/cctest/compiler/call-tester.h" + +using namespace v8::base; +using namespace v8::internal; +using namespace v8::internal::compiler; + +#define __ masm. + +static int64_t DummyStaticFunction(Object* result) { return 1; } + +TEST(WasmRelocationArm64) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + v8::internal::byte buffer[4096]; + DummyStaticFunction(NULL); + int64_t imm = 1234567; + + MacroAssembler masm(isolate, buffer, sizeof buffer, + v8::internal::CodeObjectRequired::kYes); + + __ Mov(x0, Immediate(imm, RelocInfo::WASM_MEMORY_REFERENCE)); + __ Ret(); + + CodeDesc desc; + masm.GetCode(&desc); + Handle code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle()); + + CSignature0 csig; + CodeRunner runnable(isolate, code, &csig); + int64_t ret_value = runnable.Call(); + CHECK_EQ(ret_value, imm); + +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); + ::printf("f() = %ld\n\n", ret_value); +#endif + size_t offset = 1234; + + // Relocating reference by offset + 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)) { + // Dummy values of size used here as the objective of the test is to + // verify that the immediate is patched correctly + it.rinfo()->update_wasm_memory_reference( + it.rinfo()->wasm_memory_reference(), + it.rinfo()->wasm_memory_reference() + offset, 1, 2, + SKIP_ICACHE_FLUSH); + } + } + + // Call into relocated code object + ret_value = runnable.Call(); + CHECK_EQ((imm + offset), ret_value); + +#ifdef DEBUG + code->Print(os); + ::printf("f() = %ld\n\n", ret_value); +#endif +} + +#undef __ diff --git a/test/cctest/test-run-wasm-relocation-ia32.cc b/test/cctest/test-run-wasm-relocation-ia32.cc new file mode 100644 index 0000000000..ed696e17c1 --- /dev/null +++ b/test/cctest/test-run-wasm-relocation-ia32.cc @@ -0,0 +1,89 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "src/v8.h" + +#include "src/debug/debug.h" +#include "src/disasm.h" +#include "src/disassembler.h" +#include "src/ia32/frames-ia32.h" +#include "src/ic/ic.h" +#include "src/macro-assembler.h" +#include "test/cctest/cctest.h" +#include "test/cctest/compiler/c-signature.h" +#include "test/cctest/compiler/call-tester.h" + +using namespace v8::internal; +using namespace v8::internal::compiler; + +#define __ assm. + +static int32_t DummyStaticFunction(Object* result) { return 1; } + +TEST(WasmRelocationIa32) { + CcTest::InitializeVM(); + Zone zone; + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + v8::internal::byte buffer[4096]; + Assembler assm(isolate, buffer, sizeof buffer); + DummyStaticFunction(NULL); + int32_t imm = 1234567; + + __ mov(eax, Immediate(reinterpret_cast
(imm), + RelocInfo::WASM_MEMORY_REFERENCE)); + __ nop(); + __ ret(0); + + CSignature0 csig; + CodeDesc desc; + assm.GetCode(&desc); + Handle code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle()); + USE(code); + + CodeRunner runnable(isolate, code, &csig); + int32_t ret_value = runnable.Call(); + CHECK_EQ(ret_value, imm); + +#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 = 1234; + + // Relocating references by offset + 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)) { + // Dummy values of size used here as the objective of the test is to + // verify that the immediate is patched correctly + it.rinfo()->update_wasm_memory_reference( + it.rinfo()->wasm_memory_reference(), + it.rinfo()->wasm_memory_reference() + offset, 1, 2, + SKIP_ICACHE_FLUSH); + } + } + + // Check if immediate is updated correctly + ret_value = runnable.Call(); + CHECK_EQ(ret_value, imm + offset); + +#ifdef OBJECT_PRINT + // OFStream os(stdout); + code->Print(os); + begin = code->instruction_start(); + end = begin + code->instruction_size(); + disasm::Disassembler::Disassemble(stdout, begin, end); +#endif +} + +#undef __ diff --git a/test/cctest/test-run-wasm-relocation-x64.cc b/test/cctest/test-run-wasm-relocation-x64.cc new file mode 100644 index 0000000000..11e1eb2794 --- /dev/null +++ b/test/cctest/test-run-wasm-relocation-x64.cc @@ -0,0 +1,84 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "src/v8.h" + +#include "src/debug/debug.h" +#include "src/disasm.h" +#include "src/disassembler.h" +#include "src/ic/ic.h" +#include "src/macro-assembler.h" +#include "test/cctest/cctest.h" +#include "test/cctest/compiler/c-signature.h" +#include "test/cctest/compiler/call-tester.h" + +using namespace v8::internal; +using namespace v8::internal::compiler; + +#define __ assm. + +static int32_t DummyStaticFunction(Object* result) { return 1; } +TEST(WasmRelocationX64movq64) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + v8::internal::byte buffer[4096]; + Assembler assm(isolate, buffer, sizeof buffer); + DummyStaticFunction(NULL); + int64_t imm = 1234567; + + __ movq(rax, imm, RelocInfo::WASM_MEMORY_REFERENCE); + __ nop(); + __ ret(0); + + CodeDesc desc; + assm.GetCode(&desc); + Handle code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle()); + USE(code); + + CSignature0 csig; + CodeRunner runnable(isolate, code, &csig); + int64_t ret_value = runnable.Call(); + CHECK_EQ(ret_value, imm); + +#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 = 1234; + + // Relocating references by offset + 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)) { + // Dummy values of size used here as the objective of the test is to + // verify that the immediate is patched correctly + it.rinfo()->update_wasm_memory_reference( + it.rinfo()->wasm_memory_reference(), + it.rinfo()->wasm_memory_reference() + offset, 1, 2, + SKIP_ICACHE_FLUSH); + } + } + + // Check if immediate is updated correctly + ret_value = runnable.Call(); + printf("\nret_value: %lx", ret_value); + CHECK_EQ(ret_value, imm + offset); + +#ifdef OBJECT_PRINT + code->Print(os); + begin = code->instruction_start(); + end = begin + code->instruction_size(); + disasm::Disassembler::Disassemble(stdout, begin, end); +#endif +} + +#undef __