Commit 65070355 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[ia32,root] Add indirect calls and jumps through virtual register

This adds a temporary mechanism for isolate-independent calls and
jumps.  The problem was that - as ia32 doesn't have a scratch register
- Call and Jump cannot call through a register. This CL adds a
so-called virtual register (= a pointer-sized field) on IsolateData.

The virtual register can be removed once pc-relative calls are
implemented and all builtins have been embedded.

Bug: v8:6666
Change-Id: I1f9d8a25643fad0b3919dd813dbe219d20fcc6bc
Reviewed-on: https://chromium-review.googlesource.com/c/1282991
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56693}
parent 7d871931
This diff is collapsed.
......@@ -1891,15 +1891,20 @@ void TurboAssembler::CallCFunction(Register function, int num_arguments) {
void TurboAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) {
if (FLAG_embedded_builtins) {
// TODO(jgruber): Pc-relative builtin-to-builtin calls.
if (root_array_available_ && options().isolate_independent_code) {
// TODO(jgruber): There's no scratch register on ia32. Any call that
// requires loading a code object from the builtins constant table must:
// 1) spill two scratch registers, 2) load the target into scratch1, 3)
// store the target into a virtual register on the isolate using scratch2,
// 4) restore both scratch registers, and finally 5) call through the
// virtual register. All affected call sites should vanish once all
// builtins are embedded on ia32.
UNREACHABLE();
if (root_array_available_ && ShouldGenerateIsolateIndependentCode() &&
Builtins::IsBuiltin(*code_object)) {
// Since we don't have a scratch register available we call through a
// so-called virtual register.
// TODO(v8:6666): Remove once pc-relative jumps are supported on ia32.
Assembler::AllowExplicitEbxAccessScope read_only_access(this);
Operand virtual_call_target_register(
kRootRegister,
IsolateData::kVirtualCallTargetRegisterOffset - kRootRegisterBias);
Move(virtual_call_target_register, Immediate(code_object));
add(virtual_call_target_register,
Immediate(Code::kHeaderSize - kHeapObjectTag));
call(virtual_call_target_register);
return;
} else if (options().inline_offheap_trampolines) {
int builtin_index = Builtins::kNoBuiltinId;
if (isolate()->builtins()->IsBuiltinHandle(code_object, &builtin_index) &&
......@@ -1921,15 +1926,20 @@ void TurboAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) {
void TurboAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
if (FLAG_embedded_builtins) {
// TODO(jgruber): Pc-relative builtin-to-builtin calls.
if (root_array_available_ && options().isolate_independent_code) {
// TODO(jgruber): There's no scratch register on ia32. Any call that
// requires loading a code object from the builtins constant table must:
// 1) spill two scratch registers, 2) load the target into scratch1, 3)
// store the target into a virtual register on the isolate using scratch2,
// 4) restore both scratch registers, and finally 5) call through the
// virtual register. All affected call sites should vanish once all
// builtins are embedded on ia32.
UNREACHABLE();
if (root_array_available_ && ShouldGenerateIsolateIndependentCode() &&
Builtins::IsBuiltin(*code_object)) {
// Since we don't have a scratch register available we call through a
// so-called virtual register.
// TODO(v8:6666): Remove once pc-relative jumps are supported on ia32.
Assembler::AllowExplicitEbxAccessScope read_only_access(this);
Operand virtual_call_target_register(
kRootRegister,
IsolateData::kVirtualCallTargetRegisterOffset - kRootRegisterBias);
Move(virtual_call_target_register, Immediate(code_object));
add(virtual_call_target_register,
Immediate(Code::kHeaderSize - kHeapObjectTag));
jmp(virtual_call_target_register);
return;
} else if (options().inline_offheap_trampolines) {
int builtin_index = Builtins::kNoBuiltinId;
if (isolate()->builtins()->IsBuiltinHandle(code_object, &builtin_index) &&
......
......@@ -39,7 +39,8 @@ class IsolateData final {
V(kBuiltinsTableEndOffset, 0) \
/* magic_number_ */ \
V(kMagicNumberOffset, kIntptrSize) \
V(kMagicNumberEndOffset, 0) \
/* virtual_call_target_register_ */ \
V(kVirtualCallTargetRegisterOffset, kPointerSize) \
/* Total size. */ \
V(kSize, 0)
......@@ -79,6 +80,10 @@ class IsolateData final {
// TODO(v8:6666): Remove once the root register is fully supported on ia32.
const intptr_t magic_number_ = kRootRegisterSentinel;
// For isolate-independent calls on ia32.
// TODO(v8:6666): Remove once pc-relative jumps are supported on ia32.
void* virtual_call_target_register_ = nullptr;
V8_INLINE static void AssertPredictableLayout();
friend class Isolate;
......
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