Commit 6cd28b52 authored by Emanuel Ziegler's avatar Emanuel Ziegler Committed by Commit Bot

[wasm] Save FP & PC when calling C functions

Added implementations for ia32, arm, arm64.

mips/mips64 will be committed in separate CL once the build is green
again in order not to stall this CL with the supported architectures.

Drive-by: Fixed issues with kScratchRegister being overwritten in case of RegExp
compilation by using alternative temp register for x64.

Drive-by: Added missing NoRootArrayScope to ia32, arm and arm64 RegExp
macro assemblers.

R=clemensb@chromium.org
R=petermarshall@chromium.org
R=jgruber@chromium.org

Bug: chromium:1045860
Change-Id: I716d852b9bf780ae7b8d61376c6505dd3af96a50
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2071866
Commit-Queue: Emanuel Ziegler <ecmziegler@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66482}
parent 74895882
...@@ -2366,15 +2366,25 @@ void TurboAssembler::CallCFunctionHelper(Register function, ...@@ -2366,15 +2366,25 @@ void TurboAssembler::CallCFunctionHelper(Register function,
// Save the frame pointer and PC so that the stack layout remains iterable, // Save the frame pointer and PC so that the stack layout remains iterable,
// even without an ExitFrame which normally exists between JS and C frames. // even without an ExitFrame which normally exists between JS and C frames.
if (isolate() != nullptr) { Register addr_scratch = r4;
Register scratch = r4; // See x64 code for reasoning about how to address the isolate data fields.
Push(scratch); if (root_array_available()) {
str(pc,
MemOperand(kRootRegister, IsolateData::fast_c_call_caller_pc_offset()));
str(fp,
MemOperand(kRootRegister, IsolateData::fast_c_call_caller_fp_offset()));
} else {
DCHECK_NOT_NULL(isolate());
Push(addr_scratch);
Move(addr_scratch,
ExternalReference::fast_c_call_caller_pc_address(isolate()));
str(pc, MemOperand(addr_scratch));
Move(addr_scratch,
ExternalReference::fast_c_call_caller_fp_address(isolate()));
str(fp, MemOperand(addr_scratch));
Move(scratch, ExternalReference::fast_c_call_caller_pc_address(isolate())); Pop(addr_scratch);
str(pc, MemOperand(scratch));
Move(scratch, ExternalReference::fast_c_call_caller_fp_address(isolate()));
str(fp, MemOperand(scratch));
Pop(scratch);
} }
// Just call directly. The function called cannot cause a GC, or // Just call directly. The function called cannot cause a GC, or
...@@ -2382,19 +2392,25 @@ void TurboAssembler::CallCFunctionHelper(Register function, ...@@ -2382,19 +2392,25 @@ void TurboAssembler::CallCFunctionHelper(Register function,
// stays correct. // stays correct.
Call(function); Call(function);
if (isolate() != nullptr) { // We don't unset the PC; the FP is the source of truth.
// We don't unset the PC; the FP is the source of truth. Register zero_scratch = r5;
Register scratch1 = r4; Push(zero_scratch);
Register scratch2 = r5; mov(zero_scratch, Operand::Zero());
Push(scratch1);
Push(scratch2); if (root_array_available()) {
Move(scratch1, ExternalReference::fast_c_call_caller_fp_address(isolate())); str(zero_scratch,
mov(scratch2, Operand::Zero()); MemOperand(kRootRegister, IsolateData::fast_c_call_caller_fp_offset()));
str(scratch2, MemOperand(scratch1)); } else {
Pop(scratch2); DCHECK_NOT_NULL(isolate());
Pop(scratch1); Push(addr_scratch);
Move(addr_scratch,
ExternalReference::fast_c_call_caller_fp_address(isolate()));
str(zero_scratch, MemOperand(addr_scratch));
Pop(addr_scratch);
} }
Pop(zero_scratch);
int stack_passed_arguments = int stack_passed_arguments =
CalculateStackPassedWords(num_reg_arguments, num_double_arguments); CalculateStackPassedWords(num_reg_arguments, num_double_arguments);
if (ActivationFrameAlignment() > kPointerSize) { if (ActivationFrameAlignment() > kPointerSize) {
......
...@@ -1633,34 +1633,47 @@ void TurboAssembler::CallCFunction(Register function, int num_of_reg_args, ...@@ -1633,34 +1633,47 @@ void TurboAssembler::CallCFunction(Register function, int num_of_reg_args,
// Save the frame pointer and PC so that the stack layout remains iterable, // Save the frame pointer and PC so that the stack layout remains iterable,
// even without an ExitFrame which normally exists between JS and C frames. // even without an ExitFrame which normally exists between JS and C frames.
if (isolate() != nullptr) { Register pc_scratch = x4;
Register scratch1 = x4; Register addr_scratch = x5;
Register scratch2 = x5; Push(pc_scratch, addr_scratch);
Push(scratch1, scratch2);
Label get_pc;
Label get_pc; Bind(&get_pc);
Bind(&get_pc); Adr(pc_scratch, &get_pc);
Adr(scratch2, &get_pc);
// See x64 code for reasoning about how to address the isolate data fields.
Mov(scratch1, ExternalReference::fast_c_call_caller_pc_address(isolate())); if (root_array_available()) {
Str(scratch2, MemOperand(scratch1)); Str(pc_scratch,
Mov(scratch1, ExternalReference::fast_c_call_caller_fp_address(isolate())); MemOperand(kRootRegister, IsolateData::fast_c_call_caller_pc_offset()));
Str(fp, MemOperand(scratch1)); Str(fp,
MemOperand(kRootRegister, IsolateData::fast_c_call_caller_fp_offset()));
Pop(scratch2, scratch1); } else {
DCHECK_NOT_NULL(isolate());
Mov(addr_scratch,
ExternalReference::fast_c_call_caller_pc_address(isolate()));
Str(pc_scratch, MemOperand(addr_scratch));
Mov(addr_scratch,
ExternalReference::fast_c_call_caller_fp_address(isolate()));
Str(fp, MemOperand(addr_scratch));
} }
Pop(addr_scratch, pc_scratch);
// Call directly. The function called cannot cause a GC, or allow preemption, // Call directly. The function called cannot cause a GC, or allow preemption,
// so the return address in the link register stays correct. // so the return address in the link register stays correct.
Call(function); Call(function);
if (isolate() != nullptr) { // We don't unset the PC; the FP is the source of truth.
// We don't unset the PC; the FP is the source of truth. if (root_array_available()) {
Register scratch = x4; Str(xzr,
Push(scratch, xzr); MemOperand(kRootRegister, IsolateData::fast_c_call_caller_fp_offset()));
Mov(scratch, ExternalReference::fast_c_call_caller_fp_address(isolate())); } else {
Str(xzr, MemOperand(scratch)); DCHECK_NOT_NULL(isolate());
Pop(xzr, scratch); Push(addr_scratch, xzr);
Mov(addr_scratch,
ExternalReference::fast_c_call_caller_fp_address(isolate()));
Str(xzr, MemOperand(addr_scratch));
Pop(xzr, addr_scratch);
} }
if (num_of_reg_args > kRegisterPassedArguments) { if (num_of_reg_args > kRegisterPassedArguments) {
......
...@@ -1764,32 +1764,38 @@ void TurboAssembler::CallCFunction(Register function, int num_arguments) { ...@@ -1764,32 +1764,38 @@ void TurboAssembler::CallCFunction(Register function, int num_arguments) {
// Save the frame pointer and PC so that the stack layout remains iterable, // Save the frame pointer and PC so that the stack layout remains iterable,
// even without an ExitFrame which normally exists between JS and C frames. // even without an ExitFrame which normally exists between JS and C frames.
if (isolate() != nullptr) { // Find two caller-saved scratch registers.
// Find two caller-saved scratch registers. Register pc_scratch = eax;
Register scratch1 = eax; Register scratch = ecx;
Register scratch2 = ecx; if (function == eax) pc_scratch = edx;
if (function == eax) scratch1 = edx; if (function == ecx) scratch = edx;
if (function == ecx) scratch2 = edx; PushPC();
PushPC(); pop(pc_scratch);
pop(scratch1);
mov(ExternalReferenceAsOperand( // See x64 code for reasoning about how to address the isolate data fields.
ExternalReference::fast_c_call_caller_pc_address(isolate()), DCHECK_IMPLIES(!root_array_available(), isolate() != nullptr);
scratch2), mov(root_array_available()
scratch1); ? Operand(kRootRegister, IsolateData::fast_c_call_caller_pc_offset())
mov(ExternalReferenceAsOperand( : ExternalReferenceAsOperand(
ExternalReference::fast_c_call_caller_fp_address(isolate()), ExternalReference::fast_c_call_caller_pc_address(isolate()),
scratch2), scratch),
ebp); pc_scratch);
} mov(root_array_available()
? Operand(kRootRegister, IsolateData::fast_c_call_caller_fp_offset())
: ExternalReferenceAsOperand(
ExternalReference::fast_c_call_caller_fp_address(isolate()),
scratch),
ebp);
call(function); call(function);
if (isolate() != nullptr) { // We don't unset the PC; the FP is the source of truth.
// We don't unset the PC; the FP is the source of truth. mov(root_array_available()
mov(ExternalReferenceAsOperand( ? Operand(kRootRegister, IsolateData::fast_c_call_caller_fp_offset())
ExternalReference::fast_c_call_caller_fp_address(isolate()), edx), : ExternalReferenceAsOperand(
Immediate(0)); ExternalReference::fast_c_call_caller_fp_address(isolate()),
} scratch),
Immediate(0));
if (base::OS::ActivationFrameAlignment() != 0) { if (base::OS::ActivationFrameAlignment() != 0) {
mov(esp, Operand(esp, num_arguments * kSystemPointerSize)); mov(esp, Operand(esp, num_arguments * kSystemPointerSize));
......
...@@ -2651,35 +2651,60 @@ void TurboAssembler::CallCFunction(Register function, int num_arguments) { ...@@ -2651,35 +2651,60 @@ void TurboAssembler::CallCFunction(Register function, int num_arguments) {
// Save the frame pointer and PC so that the stack layout remains iterable, // Save the frame pointer and PC so that the stack layout remains iterable,
// even without an ExitFrame which normally exists between JS and C frames. // even without an ExitFrame which normally exists between JS and C frames.
if (isolate() != nullptr || root_array_available_) { Label get_pc;
Label get_pc; DCHECK(!AreAliased(kScratchRegister, function));
DCHECK(!AreAliased(kScratchRegister, function)); leaq(kScratchRegister, Operand(&get_pc, 0));
leaq(kScratchRegister, Operand(&get_pc, 0)); bind(&get_pc);
bind(&get_pc);
movq(isolate() != nullptr // Addressing the following external references is tricky because we need
? ExternalReferenceAsOperand( // this to work in three situations:
ExternalReference::fast_c_call_caller_pc_address(isolate())) // 1. In wasm compilation, the isolate is nullptr and thus no
: Operand(kRootRegister, // ExternalReference can be created, but we can construct the address
IsolateData::fast_c_call_caller_pc_offset()), // directly using the root register and a static offset.
// 2. In normal JIT (and builtin) compilation, the external reference is
// usually addressed through the root register, so we can use the direct
// offset directly in most cases.
// 3. In regexp compilation, the external reference is embedded into the reloc
// info.
// The solution here is to use root register offsets wherever possible in
// which case we can construct it directly. When falling back to external
// references we need to ensure that the scratch register does not get
// accidentally overwritten. If we run into more such cases in the future, we
// should implement a more general solution.
if (root_array_available()) {
movq(Operand(kRootRegister, IsolateData::fast_c_call_caller_pc_offset()),
kScratchRegister); kScratchRegister);
movq(isolate() != nullptr movq(Operand(kRootRegister, IsolateData::fast_c_call_caller_fp_offset()),
? ExternalReferenceAsOperand( rbp);
ExternalReference::fast_c_call_caller_fp_address(isolate())) } else {
: Operand(kRootRegister, DCHECK_NOT_NULL(isolate());
IsolateData::fast_c_call_caller_fp_offset()), // Use alternative scratch register in order not to overwrite
// kScratchRegister.
Register scratch = r12;
pushq(scratch);
movq(ExternalReferenceAsOperand(
ExternalReference::fast_c_call_caller_pc_address(isolate()),
scratch),
kScratchRegister);
movq(ExternalReferenceAsOperand(
ExternalReference::fast_c_call_caller_fp_address(isolate())),
rbp); rbp);
popq(scratch);
} }
call(function); call(function);
// We don't unset the PC; the FP is the source of truth. // We don't unset the PC; the FP is the source of truth.
if (isolate() != nullptr) { if (root_array_available()) {
movq(Operand(kRootRegister, IsolateData::fast_c_call_caller_fp_offset()),
Immediate(0));
} else {
DCHECK_NOT_NULL(isolate());
movq(ExternalReferenceAsOperand( movq(ExternalReferenceAsOperand(
ExternalReference::fast_c_call_caller_fp_address(isolate())), ExternalReference::fast_c_call_caller_fp_address(isolate())),
Immediate(0)); Immediate(0));
} else if (root_array_available_) {
movq(Operand(kRootRegister, IsolateData::fast_c_call_caller_fp_offset()),
Immediate(0));
} }
DCHECK_NE(base::OS::ActivationFrameAlignment(), 0); DCHECK_NE(base::OS::ActivationFrameAlignment(), 0);
......
...@@ -102,6 +102,7 @@ RegExpMacroAssemblerARM::RegExpMacroAssemblerARM(Isolate* isolate, Zone* zone, ...@@ -102,6 +102,7 @@ RegExpMacroAssemblerARM::RegExpMacroAssemblerARM(Isolate* isolate, Zone* zone,
: NativeRegExpMacroAssembler(isolate, zone), : NativeRegExpMacroAssembler(isolate, zone),
masm_(new MacroAssembler(isolate, CodeObjectRequired::kYes, masm_(new MacroAssembler(isolate, CodeObjectRequired::kYes,
NewAssemblerBuffer(kRegExpCodeSize))), NewAssemblerBuffer(kRegExpCodeSize))),
no_root_array_scope_(masm_),
mode_(mode), mode_(mode),
num_registers_(registers_to_save), num_registers_(registers_to_save),
num_saved_registers_(registers_to_save), num_saved_registers_(registers_to_save),
......
...@@ -189,6 +189,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM ...@@ -189,6 +189,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM
Isolate* isolate() const { return masm_->isolate(); } Isolate* isolate() const { return masm_->isolate(); }
MacroAssembler* masm_; MacroAssembler* masm_;
NoRootArrayScope no_root_array_scope_;
// Which mode to generate code for (Latin1 or UC16). // Which mode to generate code for (Latin1 or UC16).
Mode mode_; Mode mode_;
......
...@@ -112,6 +112,7 @@ RegExpMacroAssemblerARM64::RegExpMacroAssemblerARM64(Isolate* isolate, ...@@ -112,6 +112,7 @@ RegExpMacroAssemblerARM64::RegExpMacroAssemblerARM64(Isolate* isolate,
: NativeRegExpMacroAssembler(isolate, zone), : NativeRegExpMacroAssembler(isolate, zone),
masm_(new MacroAssembler(isolate, CodeObjectRequired::kYes, masm_(new MacroAssembler(isolate, CodeObjectRequired::kYes,
NewAssemblerBuffer(kRegExpCodeSize))), NewAssemblerBuffer(kRegExpCodeSize))),
no_root_array_scope_(masm_),
mode_(mode), mode_(mode),
num_registers_(registers_to_save), num_registers_(registers_to_save),
num_saved_registers_(registers_to_save), num_saved_registers_(registers_to_save),
......
...@@ -264,6 +264,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM64 ...@@ -264,6 +264,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerARM64
Isolate* isolate() const { return masm_->isolate(); } Isolate* isolate() const { return masm_->isolate(); }
MacroAssembler* masm_; MacroAssembler* masm_;
NoRootArrayScope no_root_array_scope_;
// Which mode to generate code for (LATIN1 or UC16). // Which mode to generate code for (LATIN1 or UC16).
Mode mode_; Mode mode_;
......
...@@ -90,6 +90,7 @@ RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(Isolate* isolate, Zone* zone, ...@@ -90,6 +90,7 @@ RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(Isolate* isolate, Zone* zone,
: NativeRegExpMacroAssembler(isolate, zone), : NativeRegExpMacroAssembler(isolate, zone),
masm_(new MacroAssembler(isolate, CodeObjectRequired::kYes, masm_(new MacroAssembler(isolate, CodeObjectRequired::kYes,
NewAssemblerBuffer(kRegExpCodeSize))), NewAssemblerBuffer(kRegExpCodeSize))),
no_root_array_scope_(masm_),
mode_(mode), mode_(mode),
num_registers_(registers_to_save), num_registers_(registers_to_save),
num_saved_registers_(registers_to_save), num_saved_registers_(registers_to_save),
......
...@@ -178,6 +178,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerIA32 ...@@ -178,6 +178,7 @@ class V8_EXPORT_PRIVATE RegExpMacroAssemblerIA32
Isolate* isolate() const { return masm_->isolate(); } Isolate* isolate() const { return masm_->isolate(); }
MacroAssembler* masm_; MacroAssembler* masm_;
NoRootArrayScope no_root_array_scope_;
// Which mode to generate code for (LATIN1 or UC16). // Which mode to generate code for (LATIN1 or UC16).
Mode mode_; Mode mode_;
......
...@@ -32,14 +32,15 @@ class TurboAssemblerTest : public TestWithIsolate {}; ...@@ -32,14 +32,15 @@ class TurboAssemblerTest : public TestWithIsolate {};
TEST_F(TurboAssemblerTest, TestHardAbort) { TEST_F(TurboAssemblerTest, TestHardAbort) {
auto buffer = AllocateAssemblerBuffer(); auto buffer = AllocateAssemblerBuffer();
TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo,
buffer->CreateView()); buffer->CreateView());
__ set_root_array_available(false);
__ set_abort_hard(true); __ set_abort_hard(true);
__ Abort(AbortReason::kNoReason); __ Abort(AbortReason::kNoReason);
CodeDesc desc; CodeDesc desc;
tasm.GetCode(nullptr, &desc); tasm.GetCode(isolate(), &desc);
buffer->MakeExecutable(); buffer->MakeExecutable();
// We need an isolate here to execute in the simulator. // We need an isolate here to execute in the simulator.
auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start()); auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start());
...@@ -49,8 +50,9 @@ TEST_F(TurboAssemblerTest, TestHardAbort) { ...@@ -49,8 +50,9 @@ TEST_F(TurboAssemblerTest, TestHardAbort) {
TEST_F(TurboAssemblerTest, TestCheck) { TEST_F(TurboAssemblerTest, TestCheck) {
auto buffer = AllocateAssemblerBuffer(); auto buffer = AllocateAssemblerBuffer();
TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo,
buffer->CreateView()); buffer->CreateView());
__ set_root_array_available(false);
__ set_abort_hard(true); __ set_abort_hard(true);
// Fail if the first parameter is 17. // Fail if the first parameter is 17.
...@@ -60,7 +62,7 @@ TEST_F(TurboAssemblerTest, TestCheck) { ...@@ -60,7 +62,7 @@ TEST_F(TurboAssemblerTest, TestCheck) {
__ Ret(); __ Ret();
CodeDesc desc; CodeDesc desc;
tasm.GetCode(nullptr, &desc); tasm.GetCode(isolate(), &desc);
buffer->MakeExecutable(); buffer->MakeExecutable();
// We need an isolate here to execute in the simulator. // We need an isolate here to execute in the simulator.
auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start()); auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start());
......
...@@ -32,14 +32,15 @@ class TurboAssemblerTest : public TestWithIsolate {}; ...@@ -32,14 +32,15 @@ class TurboAssemblerTest : public TestWithIsolate {};
TEST_F(TurboAssemblerTest, TestHardAbort) { TEST_F(TurboAssemblerTest, TestHardAbort) {
auto buffer = AllocateAssemblerBuffer(); auto buffer = AllocateAssemblerBuffer();
TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo,
buffer->CreateView()); buffer->CreateView());
__ set_root_array_available(false);
__ set_abort_hard(true); __ set_abort_hard(true);
__ Abort(AbortReason::kNoReason); __ Abort(AbortReason::kNoReason);
CodeDesc desc; CodeDesc desc;
tasm.GetCode(nullptr, &desc); tasm.GetCode(isolate(), &desc);
buffer->MakeExecutable(); buffer->MakeExecutable();
// We need an isolate here to execute in the simulator. // We need an isolate here to execute in the simulator.
auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start()); auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start());
...@@ -49,8 +50,9 @@ TEST_F(TurboAssemblerTest, TestHardAbort) { ...@@ -49,8 +50,9 @@ TEST_F(TurboAssemblerTest, TestHardAbort) {
TEST_F(TurboAssemblerTest, TestCheck) { TEST_F(TurboAssemblerTest, TestCheck) {
auto buffer = AllocateAssemblerBuffer(); auto buffer = AllocateAssemblerBuffer();
TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo,
buffer->CreateView()); buffer->CreateView());
__ set_root_array_available(false);
__ set_abort_hard(true); __ set_abort_hard(true);
// Fail if the first parameter is 17. // Fail if the first parameter is 17.
...@@ -60,7 +62,7 @@ TEST_F(TurboAssemblerTest, TestCheck) { ...@@ -60,7 +62,7 @@ TEST_F(TurboAssemblerTest, TestCheck) {
__ Ret(); __ Ret();
CodeDesc desc; CodeDesc desc;
tasm.GetCode(nullptr, &desc); tasm.GetCode(isolate(), &desc);
buffer->MakeExecutable(); buffer->MakeExecutable();
// We need an isolate here to execute in the simulator. // We need an isolate here to execute in the simulator.
auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start()); auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start());
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "src/codegen/macro-assembler.h" #include "src/codegen/macro-assembler.h"
#include "src/execution/simulator.h" #include "src/execution/simulator.h"
#include "test/common/assembler-tester.h" #include "test/common/assembler-tester.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest-support.h" #include "testing/gtest-support.h"
namespace v8 { namespace v8 {
...@@ -16,26 +17,30 @@ namespace internal { ...@@ -16,26 +17,30 @@ namespace internal {
// a buffer and executing them. These tests do not initialize the // a buffer and executing them. These tests do not initialize the
// V8 library, create a context, or use any V8 objects. // V8 library, create a context, or use any V8 objects.
TEST(TurboAssemblerTest, TestHardAbort) { class TurboAssemblerTest : public TestWithIsolate {};
TEST_F(TurboAssemblerTest, TestHardAbort) {
auto buffer = AllocateAssemblerBuffer(); auto buffer = AllocateAssemblerBuffer();
TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo,
buffer->CreateView()); buffer->CreateView());
__ set_root_array_available(false);
__ set_abort_hard(true); __ set_abort_hard(true);
__ Abort(AbortReason::kNoReason); __ Abort(AbortReason::kNoReason);
CodeDesc desc; CodeDesc desc;
tasm.GetCode(nullptr, &desc); tasm.GetCode(isolate(), &desc);
buffer->MakeExecutable(); buffer->MakeExecutable();
auto f = GeneratedCode<void>::FromBuffer(nullptr, buffer->start()); auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start());
ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason"); ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason");
} }
TEST(TurboAssemblerTest, TestCheck) { TEST_F(TurboAssemblerTest, TestCheck) {
auto buffer = AllocateAssemblerBuffer(); auto buffer = AllocateAssemblerBuffer();
TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo,
buffer->CreateView()); buffer->CreateView());
__ set_root_array_available(false);
__ set_abort_hard(true); __ set_abort_hard(true);
// Fail if the first parameter is 17. // Fail if the first parameter is 17.
...@@ -45,9 +50,9 @@ TEST(TurboAssemblerTest, TestCheck) { ...@@ -45,9 +50,9 @@ TEST(TurboAssemblerTest, TestCheck) {
__ ret(0); __ ret(0);
CodeDesc desc; CodeDesc desc;
tasm.GetCode(nullptr, &desc); tasm.GetCode(isolate(), &desc);
buffer->MakeExecutable(); buffer->MakeExecutable();
auto f = GeneratedCode<void, int>::FromBuffer(nullptr, buffer->start()); auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start());
f.Call(0); f.Call(0);
f.Call(18); f.Call(18);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "src/codegen/macro-assembler.h" #include "src/codegen/macro-assembler.h"
#include "src/execution/simulator.h" #include "src/execution/simulator.h"
#include "test/common/assembler-tester.h" #include "test/common/assembler-tester.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest-support.h" #include "testing/gtest-support.h"
namespace v8 { namespace v8 {
...@@ -16,26 +17,30 @@ namespace internal { ...@@ -16,26 +17,30 @@ namespace internal {
// a buffer and executing them. These tests do not initialize the // a buffer and executing them. These tests do not initialize the
// V8 library, create a context, or use any V8 objects. // V8 library, create a context, or use any V8 objects.
TEST(TurboAssemblerTest, TestHardAbort) { class TurboAssemblerTest : public TestWithIsolate {};
TEST_F(TurboAssemblerTest, TestHardAbort) {
auto buffer = AllocateAssemblerBuffer(); auto buffer = AllocateAssemblerBuffer();
TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo,
buffer->CreateView()); buffer->CreateView());
__ set_root_array_available(false);
__ set_abort_hard(true); __ set_abort_hard(true);
__ Abort(AbortReason::kNoReason); __ Abort(AbortReason::kNoReason);
CodeDesc desc; CodeDesc desc;
tasm.GetCode(nullptr, &desc); tasm.GetCode(isolate(), &desc);
buffer->MakeExecutable(); buffer->MakeExecutable();
auto f = GeneratedCode<void>::FromBuffer(nullptr, buffer->start()); auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start());
ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason"); ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason");
} }
TEST(TurboAssemblerTest, TestCheck) { TEST_F(TurboAssemblerTest, TestCheck) {
auto buffer = AllocateAssemblerBuffer(); auto buffer = AllocateAssemblerBuffer();
TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo,
buffer->CreateView()); buffer->CreateView());
__ set_root_array_available(false);
__ set_abort_hard(true); __ set_abort_hard(true);
// Fail if the first parameter is 17. // Fail if the first parameter is 17.
...@@ -45,9 +50,9 @@ TEST(TurboAssemblerTest, TestCheck) { ...@@ -45,9 +50,9 @@ TEST(TurboAssemblerTest, TestCheck) {
__ ret(0); __ ret(0);
CodeDesc desc; CodeDesc desc;
tasm.GetCode(nullptr, &desc); tasm.GetCode(isolate(), &desc);
buffer->MakeExecutable(); buffer->MakeExecutable();
auto f = GeneratedCode<void, int>::FromBuffer(nullptr, buffer->start()); auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start());
f.Call(0); f.Call(0);
f.Call(18); f.Call(18);
......
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