[wasm] Relocatable Globals.

Support for relocatable globals, to facilitate compilation before
instantiation.

BUG=v8:5072

Review-Url: https://codereview.chromium.org/2062003002
Cr-Commit-Position: refs/heads/master@{#36978}
This commit is contained in:
mtrofin 2016-06-14 14:38:21 -07:00 committed by Commit bot
parent 65c1eef8eb
commit 2d1f977c93
18 changed files with 200 additions and 12 deletions

View File

@ -249,6 +249,11 @@ uint32_t RelocInfo::wasm_memory_size_reference() {
return reinterpret_cast<uint32_t>(Assembler::target_address_at(pc_, host_));
}
Address RelocInfo::wasm_global_reference() {
DCHECK(IsWasmGlobalReference(rmode_));
return 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) {
@ -276,6 +281,17 @@ void RelocInfo::update_wasm_memory_reference(
}
}
void RelocInfo::update_wasm_global_reference(
Address old_base, Address new_base, ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmGlobalReference(rmode_));
Address updated_reference;
DCHECK(old_base <= wasm_global_reference());
updated_reference = new_base + (wasm_global_reference() - old_base);
DCHECK(new_base <= updated_reference);
Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
icache_flush_mode);
}
// -----------------------------------------------------------------------------
// Implementation of Operand and MemOperand
// See assembler-arm-inl.h for inlined constructors

View File

@ -189,6 +189,11 @@ uint32_t RelocInfo::wasm_memory_size_reference() {
return Memory::uint32_at(Assembler::target_pointer_address_at(pc_));
}
Address RelocInfo::wasm_global_reference() {
DCHECK(IsWasmGlobalReference(rmode_));
return Memory::Address_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) {
@ -215,6 +220,17 @@ void RelocInfo::update_wasm_memory_reference(
}
}
void RelocInfo::update_wasm_global_reference(
Address old_base, Address new_base, ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmGlobalReference(rmode_));
Address updated_reference;
DCHECK(old_base <= wasm_global_reference());
updated_reference = new_base + (wasm_global_reference() - old_base);
DCHECK(new_base <= updated_reference);
Assembler::set_target_address_at(isolate_, pc_, host_, updated_reference,
icache_flush_mode);
}
Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, Register reg2,
Register reg3, Register reg4) {
CPURegList regs(reg1, reg2, reg3, reg4);

View File

@ -867,6 +867,8 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
return "wasm memory reference";
case WASM_MEMORY_SIZE_REFERENCE:
return "wasm memory size reference";
case WASM_GLOBAL_REFERENCE:
return "wasm global value reference";
case NUMBER_OF_MODES:
case PC_JUMP:
UNREACHABLE();
@ -964,6 +966,7 @@ void RelocInfo::Verify(Isolate* isolate) {
case GENERATOR_CONTINUATION:
case WASM_MEMORY_REFERENCE:
case WASM_MEMORY_SIZE_REFERENCE:
case WASM_GLOBAL_REFERENCE:
case NONE32:
case NONE64:
break;

View File

@ -386,6 +386,7 @@ class RelocInfo {
EMBEDDED_OBJECT,
// To relocate pointers into the wasm memory embedded in wasm code
WASM_MEMORY_REFERENCE,
WASM_GLOBAL_REFERENCE,
WASM_MEMORY_SIZE_REFERENCE,
CELL,
@ -529,6 +530,9 @@ class RelocInfo {
static inline bool IsWasmMemorySizeReference(Mode mode) {
return mode == WASM_MEMORY_SIZE_REFERENCE;
}
static inline bool IsWasmGlobalReference(Mode mode) {
return mode == WASM_GLOBAL_REFERENCE;
}
static inline int ModeMask(Mode mode) { return 1 << mode; }
// Accessors
@ -556,10 +560,14 @@ class RelocInfo {
bool IsInConstantPool();
Address wasm_memory_reference();
Address wasm_global_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);
void update_wasm_global_reference(
Address old_base, Address new_base,
ICacheFlushMode icache_flush_mode = SKIP_ICACHE_FLUSH);
// this relocation applies to;
// can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)

View File

@ -1576,6 +1576,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
switch (src.type()) {
case Constant::kInt32:
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE ||
src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
__ mov(dst, Operand(src.ToInt32(), src.rmode()));
} else {

View File

@ -210,7 +210,8 @@ class Arm64OperandConverter final : public InstructionOperandConverter {
return Operand(constant.ToInt32());
}
case Constant::kInt64:
if (constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
if (constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
constant.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
return Operand(constant.ToInt64(), constant.rmode());
} else {
DCHECK(constant.rmode() != RelocInfo::WASM_MEMORY_SIZE_REFERENCE);

View File

@ -67,6 +67,7 @@ class IA32OperandConverter : public InstructionOperandConverter {
Constant constant = ToConstant(operand);
if (constant.type() == Constant::kInt32 &&
(constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
constant.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE ||
constant.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE)) {
return Immediate(reinterpret_cast<Address>(constant.ToInt32()),
constant.rmode());

View File

@ -1867,6 +1867,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
switch (src.type()) {
case Constant::kInt32:
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE ||
src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
__ li(dst, Operand(src.ToInt32(), src.rmode()));
} else {

View File

@ -2125,7 +2125,8 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
__ li(dst, isolate()->factory()->NewNumber(src.ToFloat32(), TENURED));
break;
case Constant::kInt64:
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
__ li(dst, Operand(src.ToInt64(), src.rmode()));
} else {
DCHECK(src.rmode() != RelocInfo::WASM_MEMORY_SIZE_REFERENCE);

View File

@ -2549,11 +2549,11 @@ Node* WasmGraphBuilder::FunctionTable() {
}
Node* WasmGraphBuilder::LoadGlobal(uint32_t index) {
DCHECK(module_ && module_->instance && module_->instance->globals_start);
MachineType mem_type = module_->GetGlobalType(index);
Node* addr = jsgraph()->IntPtrConstant(
Node* addr = jsgraph()->RelocatableIntPtrConstant(
reinterpret_cast<uintptr_t>(module_->instance->globals_start +
module_->module->globals[index].offset));
module_->module->globals[index].offset),
RelocInfo::WASM_GLOBAL_REFERENCE);
const Operator* op = jsgraph()->machine()->Load(mem_type);
Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), *effect_,
*control_);
@ -2562,11 +2562,11 @@ Node* WasmGraphBuilder::LoadGlobal(uint32_t index) {
}
Node* WasmGraphBuilder::StoreGlobal(uint32_t index, Node* val) {
DCHECK(module_ && module_->instance && module_->instance->globals_start);
MachineType mem_type = module_->GetGlobalType(index);
Node* addr = jsgraph()->IntPtrConstant(
Node* addr = jsgraph()->RelocatableIntPtrConstant(
reinterpret_cast<uintptr_t>(module_->instance->globals_start +
module_->module->globals[index].offset));
module_->module->globals[index].offset),
RelocInfo::WASM_GLOBAL_REFERENCE);
const Operator* op = jsgraph()->machine()->Store(
StoreRepresentation(mem_type.representation(), kNoWriteBarrier));
Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val,

View File

@ -41,7 +41,8 @@ class X64OperandConverter : public InstructionOperandConverter {
return Immediate(0);
}
if (constant.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
constant.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
constant.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE ||
constant.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
return Immediate(constant.ToInt32(), constant.rmode());
}
return Immediate(constant.ToInt32());
@ -2168,7 +2169,8 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
: kScratchRegister;
switch (src.type()) {
case Constant::kInt32: {
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
__ movq(dst, src.ToInt64(), src.rmode());
} else {
// TODO(dcarney): don't need scratch in this case.
@ -2182,7 +2184,8 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
break;
}
case Constant::kInt64:
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE) {
if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE ||
src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE) {
__ movq(dst, src.ToInt64(), src.rmode());
} else {
DCHECK(src.rmode() != RelocInfo::WASM_MEMORY_SIZE_REFERENCE);

View File

@ -191,6 +191,11 @@ Address RelocInfo::wasm_memory_reference() {
return Memory::Address_at(pc_);
}
Address RelocInfo::wasm_global_reference() {
DCHECK(IsWasmGlobalReference(rmode_));
return Memory::Address_at(pc_);
}
uint32_t RelocInfo::wasm_memory_size_reference() {
DCHECK(IsWasmMemorySizeReference(rmode_));
return Memory::uint32_at(pc_);
@ -223,6 +228,19 @@ void RelocInfo::update_wasm_memory_reference(
}
}
void RelocInfo::update_wasm_global_reference(
Address old_base, Address new_base, ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmGlobalReference(rmode_));
Address updated_reference;
DCHECK(old_base <= wasm_global_reference());
updated_reference = new_base + (wasm_global_reference() - old_base);
DCHECK(new_base <= updated_reference);
Memory::Address_at(pc_) = updated_reference;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
Assembler::FlushICache(isolate_, pc_, sizeof(int32_t));
}
}
// -----------------------------------------------------------------------------
// Implementation of Operand

View File

@ -194,6 +194,11 @@ Address RelocInfo::wasm_memory_reference() {
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::wasm_global_reference() {
DCHECK(IsWasmGlobalReference(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_));
@ -226,6 +231,17 @@ void RelocInfo::update_wasm_memory_reference(
}
}
void RelocInfo::update_wasm_global_reference(
Address old_base, Address new_base, ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmGlobalReference(rmode_));
Address updated_global_reference;
DCHECK(old_base <= wasm_global_reference());
updated_global_reference = new_base + (wasm_global_reference() - old_base);
DCHECK(new_base <= updated_global_reference);
Assembler::set_target_address_at(isolate_, pc_, host_,
updated_global_reference, icache_flush_mode);
}
// -----------------------------------------------------------------------------
// Implementation of Operand and MemOperand.
// See assembler-mips-inl.h for inlined constructors.

View File

@ -172,6 +172,11 @@ Address RelocInfo::wasm_memory_reference() {
return Assembler::target_address_at(pc_, host_);
}
Address RelocInfo::wasm_global_reference() {
DCHECK(IsWasmGlobalReference(rmode_));
return Assembler::target_address_at(pc_, host_);
}
uint32_t RelocInfo::wasm_memory_size_reference() {
DCHECK(IsWasmMemorySizeReference(rmode_));
return static_cast<uint32_t>(
@ -205,6 +210,17 @@ void RelocInfo::update_wasm_memory_reference(
}
}
void RelocInfo::update_wasm_global_reference(
Address old_base, Address new_base, ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmGlobalReference(rmode_));
Address updated_global_reference;
DCHECK(old_base <= wasm_global_reference());
updated_global_reference = new_base + (wasm_global_reference() - old_base);
DCHECK(new_base <= updated_global_reference);
Assembler::set_target_address_at(isolate_, pc_, host_,
updated_global_reference, icache_flush_mode);
}
// -----------------------------------------------------------------------------
// Implementation of Operand and MemOperand.
// See assembler-mips-inl.h for inlined constructors.

View File

@ -122,6 +122,11 @@ Address RelocInfo::wasm_memory_reference() {
return Memory::Address_at(pc_);
}
Address RelocInfo::wasm_global_reference() {
DCHECK(IsWasmGlobalReference(rmode_));
return Memory::Address_at(pc_);
}
uint32_t RelocInfo::wasm_memory_size_reference() {
DCHECK(IsWasmMemorySizeReference(rmode_));
return Memory::uint32_at(pc_);
@ -154,6 +159,19 @@ void RelocInfo::update_wasm_memory_reference(
}
}
void RelocInfo::update_wasm_global_reference(
Address old_base, Address new_base, ICacheFlushMode icache_flush_mode) {
DCHECK(IsWasmGlobalReference(rmode_));
Address updated_reference;
DCHECK(old_base <= wasm_global_reference());
updated_reference = new_base + (wasm_global_reference() - old_base);
DCHECK(new_base <= updated_reference);
Memory::Address_at(pc_) = updated_reference;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
Assembler::FlushICache(isolate_, pc_, sizeof(int64_t));
}
}
// -----------------------------------------------------------------------------
// Implementation of Operand

View File

@ -164,6 +164,7 @@ v8_executable("cctest") {
"wasm/test-run-wasm-interpreter.cc",
"wasm/test-run-wasm-js.cc",
"wasm/test-run-wasm-module.cc",
"wasm/test-run-wasm-relocation.cc",
"wasm/test-run-wasm.cc",
"wasm/test-signatures.h",
"wasm/test-wasm-function-name-table.cc",
@ -325,7 +326,10 @@ v8_executable("cctest") {
# Suppress warnings about importing locally defined symbols.
if (is_component_build) {
ldflags = [ "/ignore:4049", "/ignore:4217" ]
ldflags = [
"/ignore:4049",
"/ignore:4217",
]
}
}
}

View File

@ -202,6 +202,7 @@
'wasm/test-run-wasm-module.cc',
'wasm/test-signatures.h',
'wasm/test-wasm-function-name-table.cc',
'wasm/test-run-wasm-relocation.cc',
'wasm/test-wasm-stack.cc',
'wasm/test-wasm-trap-position.cc',
'wasm/wasm-run-utils.h',

View File

@ -0,0 +1,64 @@
// 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 <stdlib.h>
#include "src/v8.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/c-signature.h"
#include "test/cctest/wasm/wasm-run-utils.h"
using namespace v8::internal;
using namespace v8::internal::compiler;
#define FOREACH_TYPE(TEST_BODY) \
TEST_BODY(int8_t, Int8, WASM_I32_ADD) \
TEST_BODY(uint8_t, Uint8, WASM_I32_ADD) \
TEST_BODY(int16_t, Int16, WASM_I32_ADD) \
TEST_BODY(uint16_t, Uint16, WASM_I32_ADD) \
TEST_BODY(int32_t, Int32, WASM_I32_ADD) \
TEST_BODY(uint32_t, Uint32, WASM_I32_ADD) \
TEST_BODY(float, Float32, WASM_F32_ADD) \
TEST_BODY(double, Float64, WASM_F64_ADD)
#define LOAD_STORE_GLOBAL_TEST_BODY(C_TYPE, MACHINE_TYPE, ADD) \
TEST(WasmRelocateGlobal##MACHINE_TYPE) { \
TestingModule module(kExecuteCompiled); \
module.AddGlobal<int32_t>(MachineType::MACHINE_TYPE()); \
module.AddGlobal<int32_t>(MachineType::MACHINE_TYPE()); \
\
WasmRunner<C_TYPE> r(&module, MachineType::MACHINE_TYPE()); \
\
/* global = global + p0 */ \
BUILD(r, \
WASM_STORE_GLOBAL(1, ADD(WASM_LOAD_GLOBAL(0), WASM_GET_LOCAL(0)))); \
CHECK_EQ(1, module.instance->function_code.size()); \
\
int filter = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; \
\
Handle<Code> code = module.instance->function_code[0]; \
\
Address old_start = module.instance->globals_start; \
Address new_start = old_start + 1; \
\
Address old_addresses[2]; \
uint32_t address_index = 0U; \
for (RelocIterator it(*code, filter); !it.done(); it.next()) { \
old_addresses[address_index] = it.rinfo()->wasm_global_reference(); \
it.rinfo()->update_wasm_global_reference(old_start, new_start); \
++address_index; \
} \
CHECK_EQ(2U, address_index); \
\
address_index = 0U; \
for (RelocIterator it(*code, filter); !it.done(); it.next()) { \
CHECK_EQ(old_addresses[address_index] + 1, \
it.rinfo()->wasm_global_reference()); \
++address_index; \
} \
CHECK_EQ(2U, address_index); \
}
FOREACH_TYPE(LOAD_STORE_GLOBAL_TEST_BODY)