Commit fdb067dc authored by Mircea Trofin's avatar Mircea Trofin Committed by Commit Bot

[wasm] JIT using WasmCodeManager: codegen components.

This CL introduces those codegen changes necessary for JIT-ing using
the WasmCodeManager.

Bug: v8:6876
Change-Id: I6b463b3e278f5e53f8dfa488f76eeaeb5231dbea
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/782261Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Commit-Queue: Mircea Trofin <mtrofin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49554}
parent ed9b2072
...@@ -67,14 +67,13 @@ void RelocInfo::apply(intptr_t delta) { ...@@ -67,14 +67,13 @@ void RelocInfo::apply(intptr_t delta) {
Address RelocInfo::target_address() { Address RelocInfo::target_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_));
return Assembler::target_address_at(pc_, host_); return Assembler::target_address_at(pc_, host_);
} }
Address RelocInfo::target_address_address() { Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
|| rmode_ == EMBEDDED_OBJECT rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
|| rmode_ == EXTERNAL_REFERENCE);
if (Assembler::IsMovW(Memory::int32_at(pc_))) { if (Assembler::IsMovW(Memory::int32_at(pc_))) {
return reinterpret_cast<Address>(pc_); return reinterpret_cast<Address>(pc_);
} else { } else {
......
...@@ -357,6 +357,17 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size, ...@@ -357,6 +357,17 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size,
reinterpret_cast<Address>(size), flush_mode); reinterpret_cast<Address>(size), flush_mode);
} }
void RelocInfo::set_js_to_wasm_address(Isolate* isolate, Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
set_embedded_address(isolate, address, icache_flush_mode);
}
Address RelocInfo::js_to_wasm_address() const {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
return embedded_address();
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Implementation of Operand and MemOperand // Implementation of Operand and MemOperand
// See assembler-arm-inl.h for inlined constructors // See assembler-arm-inl.h for inlined constructors
......
...@@ -629,14 +629,13 @@ int RelocInfo::target_address_size() { ...@@ -629,14 +629,13 @@ int RelocInfo::target_address_size() {
Address RelocInfo::target_address() { Address RelocInfo::target_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_));
return Assembler::target_address_at(pc_, host_); return Assembler::target_address_at(pc_, host_);
} }
Address RelocInfo::target_address_address() { Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
|| rmode_ == EMBEDDED_OBJECT rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
|| rmode_ == EXTERNAL_REFERENCE);
return Assembler::target_pointer_address_at(pc_); return Assembler::target_pointer_address_at(pc_);
} }
......
...@@ -195,6 +195,17 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size, ...@@ -195,6 +195,17 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size,
// No icache flushing needed, see comment in set_target_address_at. // No icache flushing needed, see comment in set_target_address_at.
} }
void RelocInfo::set_js_to_wasm_address(Isolate* isolate, Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
set_embedded_address(isolate, address, icache_flush_mode);
}
Address RelocInfo::js_to_wasm_address() const {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
return embedded_address();
}
bool AreAliased(const CPURegister& reg1, const CPURegister& reg2, bool AreAliased(const CPURegister& reg1, const CPURegister& reg2,
const CPURegister& reg3, const CPURegister& reg4, const CPURegister& reg3, const CPURegister& reg4,
const CPURegister& reg5, const CPURegister& reg6, const CPURegister& reg5, const CPURegister& reg6,
......
...@@ -658,6 +658,8 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) { ...@@ -658,6 +658,8 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
return "global handle"; return "global handle";
case WASM_CALL: case WASM_CALL:
return "internal wasm call"; return "internal wasm call";
case JS_TO_WASM_CALL:
return "js to wasm call";
case NUMBER_OF_MODES: case NUMBER_OF_MODES:
case PC_JUMP: case PC_JUMP:
UNREACHABLE(); UNREACHABLE();
...@@ -740,6 +742,7 @@ void RelocInfo::Verify(Isolate* isolate) { ...@@ -740,6 +742,7 @@ void RelocInfo::Verify(Isolate* isolate) {
case WASM_FUNCTION_TABLE_SIZE_REFERENCE: case WASM_FUNCTION_TABLE_SIZE_REFERENCE:
case WASM_GLOBAL_HANDLE: case WASM_GLOBAL_HANDLE:
case WASM_CALL: case WASM_CALL:
case JS_TO_WASM_CALL:
case NONE32: case NONE32:
case NONE64: case NONE64:
break; break;
......
...@@ -367,6 +367,7 @@ class RelocInfo { ...@@ -367,6 +367,7 @@ class RelocInfo {
WASM_FUNCTION_TABLE_SIZE_REFERENCE, WASM_FUNCTION_TABLE_SIZE_REFERENCE,
WASM_GLOBAL_HANDLE, WASM_GLOBAL_HANDLE,
WASM_CALL, WASM_CALL,
JS_TO_WASM_CALL,
RUNTIME_ENTRY, RUNTIME_ENTRY,
COMMENT, COMMENT,
...@@ -470,7 +471,8 @@ class RelocInfo { ...@@ -470,7 +471,8 @@ class RelocInfo {
return IsWasmFunctionTableSizeReference(mode); return IsWasmFunctionTableSizeReference(mode);
} }
static inline bool IsWasmPtrReference(Mode mode) { static inline bool IsWasmPtrReference(Mode mode) {
return mode == WASM_CONTEXT_REFERENCE || mode == WASM_GLOBAL_HANDLE; return mode == WASM_CONTEXT_REFERENCE || mode == WASM_GLOBAL_HANDLE ||
mode == WASM_CALL || mode == JS_TO_WASM_CALL;
} }
static inline int ModeMask(Mode mode) { return 1 << mode; } static inline int ModeMask(Mode mode) { return 1 << mode; }
...@@ -500,6 +502,7 @@ class RelocInfo { ...@@ -500,6 +502,7 @@ class RelocInfo {
Address wasm_context_reference() const; Address wasm_context_reference() const;
uint32_t wasm_function_table_size_reference() const; uint32_t wasm_function_table_size_reference() const;
Address global_handle() const; Address global_handle() const;
Address js_to_wasm_address() const;
Address wasm_call_address() const; Address wasm_call_address() const;
void set_wasm_context_reference( void set_wasm_context_reference(
...@@ -519,6 +522,9 @@ class RelocInfo { ...@@ -519,6 +522,9 @@ class RelocInfo {
void set_wasm_call_address( void set_wasm_call_address(
Isolate*, Address, Isolate*, Address,
ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED); ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
void set_js_to_wasm_address(
Isolate*, Address,
ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
// this relocation applies to; // this relocation applies to;
// can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
......
...@@ -720,6 +720,28 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -720,6 +720,28 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
break; break;
} }
case kArchCallWasmFunction: {
// We must not share code targets for calls to builtins for wasm code, as
// they might need to be patched individually.
internal::Assembler::BlockCodeTargetSharingScope scope;
RelocInfo::Mode rmode = RelocInfo::JS_TO_WASM_CALL;
if (info()->IsWasm()) {
scope.Open(tasm());
rmode = RelocInfo::WASM_CALL;
}
if (instr->InputAt(0)->IsImmediate()) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt32());
__ Call(wasm_code, rmode);
} else {
__ Call(i.InputRegister(0));
}
RecordCallPosition(instr);
DCHECK_EQ(LeaveCC, i.OutputSBit());
frame_access_state()->ClearSPDelta();
break;
}
case kArchTailCallCodeObjectFromJSFunction: case kArchTailCallCodeObjectFromJSFunction:
case kArchTailCallCodeObject: { case kArchTailCallCodeObject: {
// We must not share code targets for calls to builtins for wasm code, as // We must not share code targets for calls to builtins for wasm code, as
...@@ -745,6 +767,29 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -745,6 +767,29 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
break; break;
} }
case kArchTailCallWasm: {
// We must not share code targets for calls to builtins for wasm code, as
// they might need to be patched individually.
internal::Assembler::BlockCodeTargetSharingScope scope;
RelocInfo::Mode rmode = RelocInfo::JS_TO_WASM_CALL;
if (info()->IsWasm()) {
scope.Open(tasm());
rmode = RelocInfo::WASM_CALL;
}
if (instr->InputAt(0)->IsImmediate()) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt32());
__ Jump(wasm_code, rmode);
} else {
__ Jump(i.InputRegister(0));
}
DCHECK_EQ(LeaveCC, i.OutputSBit());
unwinding_info_writer_.MarkBlockWillExit();
frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault();
break;
}
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!instr->InputAt(0)->IsImmediate()); CHECK(!instr->InputAt(0)->IsImmediate());
__ Jump(i.InputRegister(0)); __ Jump(i.InputRegister(0));
......
...@@ -715,6 +715,40 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -715,6 +715,40 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
break; break;
} }
case kArchCallWasmFunction: {
// We must not share code targets for calls to builtins for wasm code, as
// they might need to be patched individually.
internal::Assembler::BlockCodeTargetSharingScope scope;
if (info()->IsWasm()) scope.Open(tasm());
if (instr->InputAt(0)->IsImmediate()) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt64());
if (info()->IsWasm()) {
__ Call(wasm_code, RelocInfo::WASM_CALL);
} else {
__ Call(wasm_code, RelocInfo::JS_TO_WASM_CALL);
}
} else {
Register target = i.InputRegister(0);
__ Call(target);
}
RecordCallPosition(instr);
// TODO(titzer): this is ugly. JSSP should be a caller-save register
// in this case, but it is not possible to express in the register
// allocator.
CallDescriptor::Flags flags(MiscField::decode(opcode));
if (flags & CallDescriptor::kRestoreJSSP) {
__ Ldr(jssp, MemOperand(csp));
__ Mov(csp, jssp);
}
if (flags & CallDescriptor::kRestoreCSP) {
__ Mov(csp, jssp);
__ AssertCspAligned();
}
frame_access_state()->ClearSPDelta();
break;
}
case kArchTailCallCodeObjectFromJSFunction: case kArchTailCallCodeObjectFromJSFunction:
case kArchTailCallCodeObject: { case kArchTailCallCodeObject: {
// We must not share code targets for calls to builtins for wasm code, as // We must not share code targets for calls to builtins for wasm code, as
...@@ -739,6 +773,30 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -739,6 +773,30 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
break; break;
} }
case kArchTailCallWasm: {
// We must not share code targets for calls to builtins for wasm code, as
// they might need to be patched individually.
internal::Assembler::BlockCodeTargetSharingScope scope;
if (info()->IsWasm()) scope.Open(tasm());
if (instr->InputAt(0)->IsImmediate()) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt64());
if (info()->IsWasm()) {
__ Jump(wasm_code, RelocInfo::WASM_CALL);
} else {
__ Jump(wasm_code, RelocInfo::JS_TO_WASM_CALL);
}
} else {
Register target = i.InputRegister(0);
__ Jump(target);
}
unwinding_info_writer_.MarkBlockWillExit();
frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault();
break;
}
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!instr->InputAt(0)->IsImmediate()); CHECK(!instr->InputAt(0)->IsImmediate());
__ Jump(i.InputRegister(0)); __ Jump(i.InputRegister(0));
...@@ -2572,7 +2630,8 @@ void CodeGenerator::AssembleConstructFrame() { ...@@ -2572,7 +2630,8 @@ void CodeGenerator::AssembleConstructFrame() {
__ Claim(shrink_slots); __ Claim(shrink_slots);
} }
break; break;
case CallDescriptor::kCallCodeObject: { case CallDescriptor::kCallCodeObject:
case CallDescriptor::kCallWasmFunction: {
UseScratchRegisterScope temps(tasm()); UseScratchRegisterScope temps(tasm());
__ Claim(shrink_slots + 1); // Claim extra slot for frame type marker. __ Claim(shrink_slots + 1); // Claim extra slot for frame type marker.
Register scratch = temps.AcquireX(); Register scratch = temps.AcquireX();
......
...@@ -960,6 +960,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -960,6 +960,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
break; break;
} }
case kArchCallWasmFunction: {
if (HasImmediateInput(instr, 0)) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt32());
if (info()->IsWasm()) {
__ wasm_call(wasm_code, RelocInfo::WASM_CALL);
} else {
__ call(wasm_code, RelocInfo::JS_TO_WASM_CALL);
}
} else {
Register reg = i.InputRegister(0);
__ call(reg);
}
RecordCallPosition(instr);
frame_access_state()->ClearSPDelta();
break;
}
case kArchTailCallCodeObjectFromJSFunction: case kArchTailCallCodeObjectFromJSFunction:
case kArchTailCallCodeObject: { case kArchTailCallCodeObject: {
if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
...@@ -978,6 +995,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -978,6 +995,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
break; break;
} }
case kArchTailCallWasm: {
if (HasImmediateInput(instr, 0)) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt32());
if (info()->IsWasm()) {
__ jmp(wasm_code, RelocInfo::WASM_CALL);
} else {
__ jmp(wasm_code, RelocInfo::JS_TO_WASM_CALL);
}
} else {
Register reg = i.InputRegister(0);
__ jmp(reg);
}
frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault();
break;
}
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!HasImmediateInput(instr, 0)); CHECK(!HasImmediateInput(instr, 0));
Register reg = i.InputRegister(0); Register reg = i.InputRegister(0);
......
...@@ -51,6 +51,8 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny }; ...@@ -51,6 +51,8 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny };
V(ArchRestoreCallerRegisters) \ V(ArchRestoreCallerRegisters) \
V(ArchCallCFunction) \ V(ArchCallCFunction) \
V(ArchPrepareTailCall) \ V(ArchPrepareTailCall) \
V(ArchCallWasmFunction) \
V(ArchTailCallWasm) \
V(ArchJmp) \ V(ArchJmp) \
V(ArchLookupSwitch) \ V(ArchLookupSwitch) \
V(ArchTableSwitch) \ V(ArchTableSwitch) \
......
...@@ -296,11 +296,13 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const { ...@@ -296,11 +296,13 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
case kArchCallCFunction: case kArchCallCFunction:
case kArchCallCodeObject: case kArchCallCodeObject:
case kArchCallJSFunction: case kArchCallJSFunction:
case kArchCallWasmFunction:
return kHasSideEffect; return kHasSideEffect;
case kArchTailCallCodeObjectFromJSFunction: case kArchTailCallCodeObjectFromJSFunction:
case kArchTailCallCodeObject: case kArchTailCallCodeObject:
case kArchTailCallAddress: case kArchTailCallAddress:
case kArchTailCallWasm:
return kHasSideEffect | kIsBlockTerminator; return kHasSideEffect | kIsBlockTerminator;
case kArchDeoptimize: case kArchDeoptimize:
......
...@@ -759,6 +759,14 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, ...@@ -759,6 +759,14 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
? g.UseImmediate(callee) ? g.UseImmediate(callee)
: g.UseRegister(callee)); : g.UseRegister(callee));
break; break;
case CallDescriptor::kCallWasmFunction:
buffer->instruction_args.push_back(
(call_address_immediate &&
(callee->opcode() == IrOpcode::kRelocatableInt64Constant ||
callee->opcode() == IrOpcode::kRelocatableInt32Constant))
? g.UseImmediate(callee)
: g.UseRegister(callee));
break;
case CallDescriptor::kCallJSFunction: case CallDescriptor::kCallJSFunction:
buffer->instruction_args.push_back( buffer->instruction_args.push_back(
g.UseLocation(callee, buffer->descriptor->GetInputLocation(0))); g.UseLocation(callee, buffer->descriptor->GetInputLocation(0)));
...@@ -2589,6 +2597,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -2589,6 +2597,9 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
case CallDescriptor::kCallJSFunction: case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags); opcode = kArchCallJSFunction | MiscField::encode(flags);
break; break;
case CallDescriptor::kCallWasmFunction:
opcode = kArchCallWasmFunction | MiscField::encode(flags);
break;
} }
// Emit the call instruction. // Emit the call instruction.
...@@ -2655,6 +2666,9 @@ void InstructionSelector::VisitTailCall(Node* node) { ...@@ -2655,6 +2666,9 @@ void InstructionSelector::VisitTailCall(Node* node) {
case CallDescriptor::kCallAddress: case CallDescriptor::kCallAddress:
opcode = kArchTailCallAddress; opcode = kArchTailCallAddress;
break; break;
case CallDescriptor::kCallWasmFunction:
opcode = kArchTailCallWasm;
break;
default: default:
UNREACHABLE(); UNREACHABLE();
return; return;
......
...@@ -901,7 +901,8 @@ class V8_EXPORT_PRIVATE Instruction final { ...@@ -901,7 +901,8 @@ class V8_EXPORT_PRIVATE Instruction final {
bool IsTailCall() const { bool IsTailCall() const {
return arch_opcode() == ArchOpcode::kArchTailCallCodeObject || return arch_opcode() == ArchOpcode::kArchTailCallCodeObject ||
arch_opcode() == ArchOpcode::kArchTailCallCodeObjectFromJSFunction || arch_opcode() == ArchOpcode::kArchTailCallCodeObjectFromJSFunction ||
arch_opcode() == ArchOpcode::kArchTailCallAddress; arch_opcode() == ArchOpcode::kArchTailCallAddress ||
arch_opcode() == ArchOpcode::kArchTailCallWasm;
} }
bool IsThrow() const { bool IsThrow() const {
return arch_opcode() == ArchOpcode::kArchThrowTerminator; return arch_opcode() == ArchOpcode::kArchThrowTerminator;
......
...@@ -37,6 +37,9 @@ std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k) { ...@@ -37,6 +37,9 @@ std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k) {
case CallDescriptor::kCallAddress: case CallDescriptor::kCallAddress:
os << "Addr"; os << "Addr";
break; break;
case CallDescriptor::kCallWasmFunction:
os << "Wasm";
break;
} }
return os; return os;
} }
...@@ -117,6 +120,7 @@ int CallDescriptor::CalculateFixedFrameSize() const { ...@@ -117,6 +120,7 @@ int CallDescriptor::CalculateFixedFrameSize() const {
CommonFrameConstants::kCPSlotCount; CommonFrameConstants::kCPSlotCount;
break; break;
case kCallCodeObject: case kCallCodeObject:
case kCallWasmFunction:
return TypedFrameConstants::kFixedSlotCount; return TypedFrameConstants::kFixedSlotCount;
} }
UNREACHABLE(); UNREACHABLE();
......
...@@ -166,9 +166,10 @@ class V8_EXPORT_PRIVATE CallDescriptor final ...@@ -166,9 +166,10 @@ class V8_EXPORT_PRIVATE CallDescriptor final
public: public:
// Describes the kind of this call, which determines the target. // Describes the kind of this call, which determines the target.
enum Kind { enum Kind {
kCallCodeObject, // target is a Code object kCallCodeObject, // target is a Code object
kCallJSFunction, // target is a JSFunction object kCallJSFunction, // target is a JSFunction object
kCallAddress // target is a machine pointer kCallAddress, // target is a machine pointer
kCallWasmFunction // target is a wasm function
}; };
enum Flag { enum Flag {
......
...@@ -780,6 +780,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -780,6 +780,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
break; break;
} }
case kArchCallWasmFunction: {
if (instr->InputAt(0)->IsImmediate()) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt32());
__ Call(wasm_code, info()->IsWasm() ? RelocInfo::WASM_CALL
: RelocInfo::JS_TO_WASM_CALL);
} else {
__ Call(at, i.InputRegister(0), 0);
}
RecordCallPosition(instr);
frame_access_state()->ClearSPDelta();
break;
}
case kArchTailCallCodeObjectFromJSFunction: case kArchTailCallCodeObjectFromJSFunction:
case kArchTailCallCodeObject: { case kArchTailCallCodeObject: {
if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
...@@ -796,6 +809,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -796,6 +809,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
break; break;
} }
case kArchTailCallWasm: {
if (instr->InputAt(0)->IsImmediate()) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt32());
__ Jump(wasm_code, info()->IsWasm() ? RelocInfo::WASM_CALL
: RelocInfo::JS_TO_WASM_CALL);
} else {
__ Jump(at, i.InputRegister(0), 0);
}
frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault();
break;
}
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!instr->InputAt(0)->IsImmediate()); CHECK(!instr->InputAt(0)->IsImmediate());
__ Jump(i.InputRegister(0)); __ Jump(i.InputRegister(0));
......
...@@ -824,6 +824,25 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -824,6 +824,25 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
break; break;
} }
case kArchCallWasmFunction: {
if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
i.TempRegister(0), i.TempRegister(1),
i.TempRegister(2));
}
if (instr->InputAt(0)->IsImmediate()) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt64());
__ Jump(wasm_code, info()->IsWasm() ? RelocInfo::WASM_CALL
: RelocInfo::JS_TO_WASM_CALL);
} else {
__ daddiu(at, i.InputRegister(0), 0);
__ Jump(at);
}
frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault();
break;
}
case kArchTailCallCodeObjectFromJSFunction: case kArchTailCallCodeObjectFromJSFunction:
case kArchTailCallCodeObject: { case kArchTailCallCodeObject: {
if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
...@@ -841,6 +860,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -841,6 +860,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
break; break;
} }
case kArchTailCallWasm: {
if (instr->InputAt(0)->IsImmediate()) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt64());
__ Jump(wasm_code, info()->IsWasm() ? RelocInfo::WASM_CALL
: RelocInfo::JS_TO_WASM_CALL);
} else {
__ daddiu(at, i.InputRegister(0), 0);
__ Jump(at);
}
frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault();
break;
}
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!instr->InputAt(0)->IsImmediate()); CHECK(!instr->InputAt(0)->IsImmediate());
__ Jump(i.InputRegister(0)); __ Jump(i.InputRegister(0));
......
...@@ -860,6 +860,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -860,6 +860,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->ClearSPDelta(); frame_access_state()->ClearSPDelta();
break; break;
} }
case kArchCallWasmFunction: {
if (HasImmediateInput(instr, 0)) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt64());
if (info()->IsWasm()) {
__ near_call(wasm_code, RelocInfo::WASM_CALL);
} else {
__ Call(wasm_code, RelocInfo::JS_TO_WASM_CALL);
}
} else {
Register reg = i.InputRegister(0);
__ call(reg);
}
RecordCallPosition(instr);
frame_access_state()->ClearSPDelta();
break;
}
case kArchTailCallCodeObjectFromJSFunction: case kArchTailCallCodeObjectFromJSFunction:
case kArchTailCallCodeObject: { case kArchTailCallCodeObject: {
if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
...@@ -880,6 +897,25 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -880,6 +897,25 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->SetFrameAccessToDefault(); frame_access_state()->SetFrameAccessToDefault();
break; break;
} }
case kArchTailCallWasm: {
if (HasImmediateInput(instr, 0)) {
Address wasm_code = reinterpret_cast<Address>(
i.ToConstant(instr->InputAt(0)).ToInt64());
if (info()->IsWasm()) {
__ near_jmp(wasm_code, RelocInfo::WASM_CALL);
} else {
__ Move(kScratchRegister, wasm_code, RelocInfo::JS_TO_WASM_CALL);
__ jmp(kScratchRegister);
}
} else {
Register reg = i.InputRegister(0);
__ jmp(reg);
}
unwinding_info_writer_.MarkBlockWillExit();
frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault();
break;
}
case kArchTailCallAddress: { case kArchTailCallAddress: {
CHECK(!HasImmediateInput(instr, 0)); CHECK(!HasImmediateInput(instr, 0));
Register reg = i.InputRegister(0); Register reg = i.InputRegister(0);
......
...@@ -56,7 +56,8 @@ static const int kNoCodeAgeSequenceLength = 5; ...@@ -56,7 +56,8 @@ static const int kNoCodeAgeSequenceLength = 5;
// The modes possibly affected by apply must be in kApplyMask. // The modes possibly affected by apply must be in kApplyMask.
void RelocInfo::apply(intptr_t delta) { void RelocInfo::apply(intptr_t delta) {
if (IsRuntimeEntry(rmode_) || IsCodeTarget(rmode_)) { if (IsRuntimeEntry(rmode_) || IsCodeTarget(rmode_) ||
rmode_ == RelocInfo::JS_TO_WASM_CALL) {
int32_t* p = reinterpret_cast<int32_t*>(pc_); int32_t* p = reinterpret_cast<int32_t*>(pc_);
*p -= delta; // Relocate entry. *p -= delta; // Relocate entry.
} else if (IsInternalReference(rmode_)) { } else if (IsInternalReference(rmode_)) {
...@@ -68,14 +69,13 @@ void RelocInfo::apply(intptr_t delta) { ...@@ -68,14 +69,13 @@ void RelocInfo::apply(intptr_t delta) {
Address RelocInfo::target_address() { Address RelocInfo::target_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_));
return Assembler::target_address_at(pc_, host_); return Assembler::target_address_at(pc_, host_);
} }
Address RelocInfo::target_address_address() { Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
|| rmode_ == EMBEDDED_OBJECT rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
|| rmode_ == EXTERNAL_REFERENCE);
return reinterpret_cast<Address>(pc_); return reinterpret_cast<Address>(pc_);
} }
...@@ -270,7 +270,7 @@ void Assembler::set_target_address_at(Isolate* isolate, Address pc, Code* code, ...@@ -270,7 +270,7 @@ void Assembler::set_target_address_at(Isolate* isolate, Address pc, Code* code,
Address target, Address target,
ICacheFlushMode icache_flush_mode) { ICacheFlushMode icache_flush_mode) {
Address constant_pool = code ? code->constant_pool() : nullptr; Address constant_pool = code ? code->constant_pool() : nullptr;
set_target_address_at(isolate, pc, constant_pool, target); set_target_address_at(isolate, pc, constant_pool, target, icache_flush_mode);
} }
Address Assembler::target_address_from_return_address(Address pc) { Address Assembler::target_address_from_return_address(Address pc) {
......
...@@ -186,9 +186,9 @@ void Displacement::init(Label* L, Type type) { ...@@ -186,9 +186,9 @@ void Displacement::init(Label* L, Type type) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Implementation of RelocInfo // Implementation of RelocInfo
const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | const int RelocInfo::kApplyMask =
1 << RelocInfo::RUNTIME_ENTRY | RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
1 << RelocInfo::INTERNAL_REFERENCE; 1 << RelocInfo::INTERNAL_REFERENCE | 1 << RelocInfo::JS_TO_WASM_CALL;
bool RelocInfo::IsCodedSpecially() { bool RelocInfo::IsCodedSpecially() {
// The deserializer needs to know whether a pointer is specially coded. Being // The deserializer needs to know whether a pointer is specially coded. Being
...@@ -223,6 +223,18 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size, ...@@ -223,6 +223,18 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size,
} }
} }
void RelocInfo::set_js_to_wasm_address(Isolate* isolate, Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
Assembler::set_target_address_at(isolate, pc_, constant_pool_, address,
icache_flush_mode);
}
Address RelocInfo::js_to_wasm_address() const {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
return Assembler::target_address_at(pc_, constant_pool_);
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Implementation of Operand // Implementation of Operand
...@@ -1631,6 +1643,11 @@ void Assembler::call(byte* entry, RelocInfo::Mode rmode) { ...@@ -1631,6 +1643,11 @@ void Assembler::call(byte* entry, RelocInfo::Mode rmode) {
} }
} }
void Assembler::wasm_call(Address entry, RelocInfo::Mode rmode) {
EnsureSpace ensure_space(this);
EMIT(0xE8);
emit(reinterpret_cast<intptr_t>(entry), rmode);
}
int Assembler::CallSize(const Operand& adr) { int Assembler::CallSize(const Operand& adr) {
// Call size is 1 (opcode) + adr.len_ (operand). // Call size is 1 (opcode) + adr.len_ (operand).
...@@ -1700,7 +1717,6 @@ void Assembler::jmp(Label* L, Label::Distance distance) { ...@@ -1700,7 +1717,6 @@ void Assembler::jmp(Label* L, Label::Distance distance) {
} }
} }
void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) { void Assembler::jmp(byte* entry, RelocInfo::Mode rmode) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
DCHECK(!RelocInfo::IsCodeTarget(rmode)); DCHECK(!RelocInfo::IsCodeTarget(rmode));
......
...@@ -857,6 +857,7 @@ class Assembler : public AssemblerBase { ...@@ -857,6 +857,7 @@ class Assembler : public AssemblerBase {
int CallSize(Handle<Code> code, RelocInfo::Mode mode); int CallSize(Handle<Code> code, RelocInfo::Mode mode);
void call(Handle<Code> code, RelocInfo::Mode rmode); void call(Handle<Code> code, RelocInfo::Mode rmode);
void call(CodeStub* stub); void call(CodeStub* stub);
void wasm_call(Address address, RelocInfo::Mode rmode);
// Jumps // Jumps
// unconditional jump to L // unconditional jump to L
......
...@@ -210,6 +210,17 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size, ...@@ -210,6 +210,17 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size,
reinterpret_cast<Address>(size), flush_mode); reinterpret_cast<Address>(size), flush_mode);
} }
void RelocInfo::set_js_to_wasm_address(Isolate* isolate, Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
set_embedded_address(isolate, address, icache_flush_mode);
}
Address RelocInfo::js_to_wasm_address() const {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
return embedded_address();
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Implementation of Operand and MemOperand. // Implementation of Operand and MemOperand.
// See assembler-mips-inl.h for inlined constructors. // See assembler-mips-inl.h for inlined constructors.
......
...@@ -189,6 +189,17 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size, ...@@ -189,6 +189,17 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size,
reinterpret_cast<Address>(size), flush_mode); reinterpret_cast<Address>(size), flush_mode);
} }
void RelocInfo::set_js_to_wasm_address(Isolate* isolate, Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
set_embedded_address(isolate, address, icache_flush_mode);
}
Address RelocInfo::js_to_wasm_address() const {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
return embedded_address();
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Implementation of Operand and MemOperand. // Implementation of Operand and MemOperand.
// See assembler-mips-inl.h for inlined constructors. // See assembler-mips-inl.h for inlined constructors.
......
...@@ -329,14 +329,13 @@ void RelocInfo::apply(intptr_t delta) { ...@@ -329,14 +329,13 @@ void RelocInfo::apply(intptr_t delta) {
Address RelocInfo::target_address() { Address RelocInfo::target_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_));
return Assembler::target_address_at(pc_, host_); return Assembler::target_address_at(pc_, host_);
} }
Address RelocInfo::target_address_address() { Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
|| rmode_ == EMBEDDED_OBJECT rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
|| rmode_ == EXTERNAL_REFERENCE);
return reinterpret_cast<Address>(pc_); return reinterpret_cast<Address>(pc_);
} }
......
...@@ -143,6 +143,17 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size, ...@@ -143,6 +143,17 @@ void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size,
} }
} }
void RelocInfo::set_js_to_wasm_address(Isolate* isolate, Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
set_embedded_address(isolate, address, icache_flush_mode);
}
Address RelocInfo::js_to_wasm_address() const {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
return embedded_address();
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Implementation of Operand // Implementation of Operand
...@@ -953,6 +964,23 @@ void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) { ...@@ -953,6 +964,23 @@ void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) {
emit_code_target(target, rmode); emit_code_target(target, rmode);
} }
void Assembler::near_call(Address addr, RelocInfo::Mode rmode) {
EnsureSpace ensure_space(this);
emit(0xE8);
intptr_t value = reinterpret_cast<intptr_t>(addr);
DCHECK(is_int32(value));
RecordRelocInfo(rmode);
emitl(static_cast<int32_t>(value));
}
void Assembler::near_jmp(Address addr, RelocInfo::Mode rmode) {
EnsureSpace ensure_space(this);
emit(0xE9);
intptr_t value = reinterpret_cast<intptr_t>(addr);
DCHECK(is_int32(value));
RecordRelocInfo(rmode);
emitl(static_cast<int32_t>(value));
}
void Assembler::call(Register adr) { void Assembler::call(Register adr) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
...@@ -4856,9 +4884,9 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { ...@@ -4856,9 +4884,9 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
reloc_info_writer.Write(&rinfo); reloc_info_writer.Write(&rinfo);
} }
const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | const int RelocInfo::kApplyMask =
1 << RelocInfo::RUNTIME_ENTRY | RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
1 << RelocInfo::INTERNAL_REFERENCE; 1 << RelocInfo::INTERNAL_REFERENCE | 1 << RelocInfo::WASM_CALL;
bool RelocInfo::IsCodedSpecially() { bool RelocInfo::IsCodedSpecially() {
// The deserializer needs to know whether a pointer is specially coded. Being // The deserializer needs to know whether a pointer is specially coded. Being
......
...@@ -885,6 +885,8 @@ class Assembler : public AssemblerBase { ...@@ -885,6 +885,8 @@ class Assembler : public AssemblerBase {
// Call near relative 32-bit displacement, relative to next instruction. // Call near relative 32-bit displacement, relative to next instruction.
void call(Label* L); void call(Label* L);
void call(Address entry, RelocInfo::Mode rmode); void call(Address entry, RelocInfo::Mode rmode);
void near_call(Address entry, RelocInfo::Mode rmode);
void near_jmp(Address entry, RelocInfo::Mode rmode);
void call(CodeStub* stub); void call(CodeStub* stub);
void call(Handle<Code> target, void call(Handle<Code> target,
RelocInfo::Mode rmode = RelocInfo::CODE_TARGET); RelocInfo::Mode rmode = RelocInfo::CODE_TARGET);
......
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