summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/arm64/code-generator-arm64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/arm64/code-generator-arm64.cc')
-rw-r--r--deps/v8/src/compiler/arm64/code-generator-arm64.cc539
1 files changed, 411 insertions, 128 deletions
diff --git a/deps/v8/src/compiler/arm64/code-generator-arm64.cc b/deps/v8/src/compiler/arm64/code-generator-arm64.cc
index 456e7e7608..39c3314888 100644
--- a/deps/v8/src/compiler/arm64/code-generator-arm64.cc
+++ b/deps/v8/src/compiler/arm64/code-generator-arm64.cc
@@ -33,6 +33,24 @@ class Arm64OperandConverter final : public InstructionOperandConverter {
return InputDoubleRegister(index);
}
+ CPURegister InputFloat32OrZeroRegister(size_t index) {
+ if (instr_->InputAt(index)->IsImmediate()) {
+ DCHECK(bit_cast<int32_t>(InputFloat32(index)) == 0);
+ return wzr;
+ }
+ DCHECK(instr_->InputAt(index)->IsFPRegister());
+ return InputDoubleRegister(index).S();
+ }
+
+ CPURegister InputFloat64OrZeroRegister(size_t index) {
+ if (instr_->InputAt(index)->IsImmediate()) {
+ DCHECK(bit_cast<int64_t>(InputDouble(index)) == 0);
+ return xzr;
+ }
+ DCHECK(instr_->InputAt(index)->IsDoubleRegister());
+ return InputDoubleRegister(index);
+ }
+
size_t OutputCount() { return instr_->OutputCount(); }
DoubleRegister OutputFloat32Register() { return OutputDoubleRegister().S(); }
@@ -101,6 +119,8 @@ class Arm64OperandConverter final : public InstructionOperandConverter {
return Operand(InputRegister32(index), SXTB);
case kMode_Operand2_R_SXTH:
return Operand(InputRegister32(index), SXTH);
+ case kMode_Operand2_R_SXTW:
+ return Operand(InputRegister32(index), SXTW);
case kMode_MRI:
case kMode_MRR:
break;
@@ -129,6 +149,8 @@ class Arm64OperandConverter final : public InstructionOperandConverter {
return Operand(InputRegister64(index), SXTB);
case kMode_Operand2_R_SXTH:
return Operand(InputRegister64(index), SXTH);
+ case kMode_Operand2_R_SXTW:
+ return Operand(InputRegister64(index), SXTW);
case kMode_MRI:
case kMode_MRR:
break;
@@ -141,7 +163,6 @@ class Arm64OperandConverter final : public InstructionOperandConverter {
const size_t index = *first_index;
switch (AddressingModeField::decode(instr_->opcode())) {
case kMode_None:
- case kMode_Operand2_R_LSL_I:
case kMode_Operand2_R_LSR_I:
case kMode_Operand2_R_ASR_I:
case kMode_Operand2_R_ROR_I:
@@ -149,7 +170,12 @@ class Arm64OperandConverter final : public InstructionOperandConverter {
case kMode_Operand2_R_UXTH:
case kMode_Operand2_R_SXTB:
case kMode_Operand2_R_SXTH:
+ case kMode_Operand2_R_SXTW:
break;
+ case kMode_Operand2_R_LSL_I:
+ *first_index += 3;
+ return MemOperand(InputRegister(index + 0), InputRegister(index + 1),
+ LSL, InputInt32(index + 2));
case kMode_MRI:
*first_index += 2;
return MemOperand(InputRegister(index + 0), InputInt32(index + 1));
@@ -183,9 +209,19 @@ class Arm64OperandConverter final : public InstructionOperandConverter {
Constant constant = ToConstant(operand);
switch (constant.type()) {
case Constant::kInt32:
- return Operand(constant.ToInt32());
+ if (constant.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) {
+ return Operand(constant.ToInt32(), constant.rmode());
+ } else {
+ return Operand(constant.ToInt32());
+ }
case Constant::kInt64:
- return Operand(constant.ToInt64());
+ 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);
+ return Operand(constant.ToInt64());
+ }
case Constant::kFloat32:
return Operand(
isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED));
@@ -206,7 +242,7 @@ class Arm64OperandConverter final : public InstructionOperandConverter {
MemOperand ToMemOperand(InstructionOperand* op, MacroAssembler* masm) const {
DCHECK_NOT_NULL(op);
- DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
+ DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
return SlotToMemOperand(AllocatedOperand::cast(op)->index(), masm);
}
@@ -272,7 +308,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
public:
OutOfLineRecordWrite(CodeGenerator* gen, Register object, Operand index,
Register value, Register scratch0, Register scratch1,
- RecordWriteMode mode)
+ RecordWriteMode mode,
+ UnwindingInfoWriter* unwinding_info_writer)
: OutOfLineCode(gen),
object_(object),
index_(index),
@@ -280,7 +317,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
scratch0_(scratch0),
scratch1_(scratch1),
mode_(mode),
- must_save_lr_(!gen->frame_access_state()->has_frame()) {}
+ must_save_lr_(!gen->frame_access_state()->has_frame()),
+ unwinding_info_writer_(unwinding_info_writer) {}
void Generate() final {
if (mode_ > RecordWriteMode::kValueIsPointer) {
@@ -297,6 +335,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
if (must_save_lr_) {
// We need to save and restore lr if the frame was elided.
__ Push(lr);
+ unwinding_info_writer_->MarkLinkRegisterOnTopOfStack(__ pc_offset(),
+ __ StackPointer());
}
RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_,
remembered_set_action, save_fp_mode);
@@ -304,6 +344,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
__ CallStub(&stub);
if (must_save_lr_) {
__ Pop(lr);
+ unwinding_info_writer_->MarkPopLinkRegisterFromTopOfStack(__ pc_offset());
}
}
@@ -315,6 +356,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
Register const scratch1_;
RecordWriteMode const mode_;
bool must_save_lr_;
+ UnwindingInfoWriter* const unwinding_info_writer_;
};
@@ -363,6 +405,10 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
case kUnorderedEqual:
case kUnorderedNotEqual:
break;
+ case kPositiveOrZero:
+ return pl;
+ case kNegative:
+ return mi;
}
UNREACHABLE();
return nv;
@@ -370,6 +416,17 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
} // namespace
+#define ASSEMBLE_BOUNDS_CHECK(offset, length, out_of_bounds) \
+ do { \
+ if (length.IsImmediate() && \
+ base::bits::IsPowerOfTwo64(length.ImmediateValue())) { \
+ __ Tst(offset, ~(length.ImmediateValue() - 1)); \
+ __ B(ne, out_of_bounds); \
+ } else { \
+ __ Cmp(offset, length); \
+ __ B(hs, out_of_bounds); \
+ } \
+ } while (0)
#define ASSEMBLE_CHECKED_LOAD_FLOAT(width) \
do { \
@@ -377,84 +434,72 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
auto buffer = i.InputRegister(0); \
auto offset = i.InputRegister32(1); \
auto length = i.InputOperand32(2); \
- __ Cmp(offset, length); \
auto ool = new (zone()) OutOfLineLoadNaN##width(this, result); \
- __ B(hs, ool->entry()); \
+ ASSEMBLE_BOUNDS_CHECK(offset, length, ool->entry()); \
__ Ldr(result, MemOperand(buffer, offset, UXTW)); \
__ Bind(ool->exit()); \
} while (0)
-
#define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \
do { \
auto result = i.OutputRegister32(); \
auto buffer = i.InputRegister(0); \
auto offset = i.InputRegister32(1); \
auto length = i.InputOperand32(2); \
- __ Cmp(offset, length); \
auto ool = new (zone()) OutOfLineLoadZero(this, result); \
- __ B(hs, ool->entry()); \
+ ASSEMBLE_BOUNDS_CHECK(offset, length, ool->entry()); \
__ asm_instr(result, MemOperand(buffer, offset, UXTW)); \
__ Bind(ool->exit()); \
} while (0)
-
#define ASSEMBLE_CHECKED_LOAD_INTEGER_64(asm_instr) \
do { \
auto result = i.OutputRegister(); \
auto buffer = i.InputRegister(0); \
auto offset = i.InputRegister32(1); \
auto length = i.InputOperand32(2); \
- __ Cmp(offset, length); \
auto ool = new (zone()) OutOfLineLoadZero(this, result); \
- __ B(hs, ool->entry()); \
+ ASSEMBLE_BOUNDS_CHECK(offset, length, ool->entry()); \
__ asm_instr(result, MemOperand(buffer, offset, UXTW)); \
__ Bind(ool->exit()); \
} while (0)
-
-#define ASSEMBLE_CHECKED_STORE_FLOAT(width) \
- do { \
- auto buffer = i.InputRegister(0); \
- auto offset = i.InputRegister32(1); \
- auto length = i.InputOperand32(2); \
- auto value = i.InputFloat##width##Register(3); \
- __ Cmp(offset, length); \
- Label done; \
- __ B(hs, &done); \
- __ Str(value, MemOperand(buffer, offset, UXTW)); \
- __ Bind(&done); \
+#define ASSEMBLE_CHECKED_STORE_FLOAT(width) \
+ do { \
+ auto buffer = i.InputRegister(0); \
+ auto offset = i.InputRegister32(1); \
+ auto length = i.InputOperand32(2); \
+ auto value = i.InputFloat##width##OrZeroRegister(3); \
+ Label done; \
+ ASSEMBLE_BOUNDS_CHECK(offset, length, &done); \
+ __ Str(value, MemOperand(buffer, offset, UXTW)); \
+ __ Bind(&done); \
} while (0)
-
#define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \
do { \
auto buffer = i.InputRegister(0); \
auto offset = i.InputRegister32(1); \
auto length = i.InputOperand32(2); \
- auto value = i.InputRegister32(3); \
- __ Cmp(offset, length); \
+ auto value = i.InputOrZeroRegister32(3); \
Label done; \
- __ B(hs, &done); \
+ ASSEMBLE_BOUNDS_CHECK(offset, length, &done); \
__ asm_instr(value, MemOperand(buffer, offset, UXTW)); \
__ Bind(&done); \
} while (0)
-
#define ASSEMBLE_CHECKED_STORE_INTEGER_64(asm_instr) \
do { \
auto buffer = i.InputRegister(0); \
auto offset = i.InputRegister32(1); \
auto length = i.InputOperand32(2); \
- auto value = i.InputRegister(3); \
- __ Cmp(offset, length); \
+ auto value = i.InputOrZeroRegister64(3); \
Label done; \
- __ B(hs, &done); \
+ ASSEMBLE_BOUNDS_CHECK(offset, length, &done); \
__ asm_instr(value, MemOperand(buffer, offset, UXTW)); \
__ Bind(&done); \
} while (0)
-
#define ASSEMBLE_SHIFT(asm_instr, width) \
do { \
if (instr->InputAt(1)->IsRegister()) { \
@@ -468,6 +513,35 @@ Condition FlagsConditionToCondition(FlagsCondition condition) {
} \
} while (0)
+#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr) \
+ do { \
+ __ asm_instr(i.OutputRegister(), \
+ MemOperand(i.InputRegister(0), i.InputRegister(1))); \
+ __ Dmb(InnerShareable, BarrierAll); \
+ } while (0)
+
+#define ASSEMBLE_ATOMIC_STORE_INTEGER(asm_instr) \
+ do { \
+ __ Dmb(InnerShareable, BarrierAll); \
+ __ asm_instr(i.InputRegister(2), \
+ MemOperand(i.InputRegister(0), i.InputRegister(1))); \
+ __ Dmb(InnerShareable, BarrierAll); \
+ } while (0)
+
+#define ASSEMBLE_IEEE754_BINOP(name) \
+ do { \
+ FrameScope scope(masm(), StackFrame::MANUAL); \
+ __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+ 0, 2); \
+ } while (0)
+
+#define ASSEMBLE_IEEE754_UNOP(name) \
+ do { \
+ FrameScope scope(masm(), StackFrame::MANUAL); \
+ __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \
+ 0, 1); \
+ } while (0)
+
void CodeGenerator::AssembleDeconstructFrame() {
const CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
if (descriptor->IsCFunctionCall() || descriptor->UseNativeStack()) {
@@ -476,23 +550,11 @@ void CodeGenerator::AssembleDeconstructFrame() {
__ Mov(jssp, fp);
}
__ Pop(fp, lr);
-}
-void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
- int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
- if (sp_slot_delta > 0) {
- __ Drop(sp_slot_delta);
- }
- frame_access_state()->SetFrameAccessToDefault();
+ unwinding_info_writer_.MarkFrameDeconstructed(__ pc_offset());
}
-
-void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
- int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
- if (sp_slot_delta < 0) {
- __ Claim(-sp_slot_delta);
- frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
- }
+void CodeGenerator::AssemblePrepareTailCall() {
if (frame_access_state()->has_frame()) {
__ Ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
__ Ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
@@ -525,8 +587,41 @@ void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg,
__ bind(&done);
}
+namespace {
+
+void AdjustStackPointerForTailCall(MacroAssembler* masm,
+ FrameAccessState* state,
+ int new_slot_above_sp,
+ bool allow_shrinkage = true) {
+ int current_sp_offset = state->GetSPToFPSlotCount() +
+ StandardFrameConstants::kFixedSlotCountAboveFp;
+ int stack_slot_delta = new_slot_above_sp - current_sp_offset;
+ if (stack_slot_delta > 0) {
+ masm->Claim(stack_slot_delta);
+ state->IncreaseSPDelta(stack_slot_delta);
+ } else if (allow_shrinkage && stack_slot_delta < 0) {
+ masm->Drop(-stack_slot_delta);
+ state->IncreaseSPDelta(stack_slot_delta);
+ }
+}
+
+} // namespace
+
+void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr,
+ int first_unused_stack_slot) {
+ AdjustStackPointerForTailCall(masm(), frame_access_state(),
+ first_unused_stack_slot, false);
+}
+
+void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
+ int first_unused_stack_slot) {
+ AdjustStackPointerForTailCall(masm(), frame_access_state(),
+ first_unused_stack_slot);
+}
+
// Assembles an instruction after register allocation, producing machine code.
-void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
+CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
+ Instruction* instr) {
Arm64OperandConverter i(this, instr);
InstructionCode opcode = instr->opcode();
ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
@@ -559,8 +654,6 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
}
case kArchTailCallCodeObjectFromJSFunction:
case kArchTailCallCodeObject: {
- int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
- AssembleDeconstructActivationRecord(stack_param_delta);
if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
i.TempRegister(0), i.TempRegister(1),
@@ -574,7 +667,17 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Add(target, target, Code::kHeaderSize - kHeapObjectTag);
__ Jump(target);
}
+ unwinding_info_writer_.MarkBlockWillExit();
frame_access_state()->ClearSPDelta();
+ frame_access_state()->SetFrameAccessToDefault();
+ break;
+ }
+ case kArchTailCallAddress: {
+ CHECK(!instr->InputAt(0)->IsImmediate());
+ __ Jump(i.InputRegister(0));
+ unwinding_info_writer_.MarkBlockWillExit();
+ frame_access_state()->ClearSPDelta();
+ frame_access_state()->SetFrameAccessToDefault();
break;
}
case kArchCallJSFunction: {
@@ -617,8 +720,6 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ cmp(cp, temp);
__ Assert(eq, kWrongFunctionContext);
}
- int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
- AssembleDeconstructActivationRecord(stack_param_delta);
if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) {
AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
i.TempRegister(0), i.TempRegister(1),
@@ -627,6 +728,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
__ Jump(x10);
frame_access_state()->ClearSPDelta();
+ frame_access_state()->SetFrameAccessToDefault();
break;
}
case kArchPrepareCallCFunction:
@@ -636,7 +738,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
UNREACHABLE();
break;
case kArchPrepareTailCall:
- AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1));
+ AssemblePrepareTailCall();
break;
case kArchCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode());
@@ -661,6 +763,17 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArchLookupSwitch:
AssembleArchLookupSwitch(instr);
break;
+ case kArchDebugBreak:
+ __ Debug("kArchDebugBreak", 0, BREAK);
+ break;
+ case kArchImpossible:
+ __ Abort(kConversionFromImpossibleValue);
+ break;
+ case kArchComment: {
+ Address comment_string = i.InputExternalReference(0).address();
+ __ RecordComment(reinterpret_cast<const char*>(comment_string));
+ break;
+ }
case kArchNop:
case kArchThrowTerminator:
// don't emit code for nops.
@@ -670,7 +783,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
Deoptimizer::BailoutType bailout_type =
Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
- AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+ CodeGenResult result =
+ AssembleDeoptimizerCall(deopt_state_id, bailout_type);
+ if (result != kSuccess) return result;
break;
}
case kArchRet:
@@ -708,8 +823,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
Register value = i.InputRegister(2);
Register scratch0 = i.TempRegister(0);
Register scratch1 = i.TempRegister(1);
- auto ool = new (zone()) OutOfLineRecordWrite(this, object, index, value,
- scratch0, scratch1, mode);
+ auto ool = new (zone())
+ OutOfLineRecordWrite(this, object, index, value, scratch0, scratch1,
+ mode, &unwinding_info_writer_);
__ Str(value, MemOperand(object, index));
__ CheckPageFlagSet(object, scratch0,
MemoryChunk::kPointersFromHereAreInterestingMask,
@@ -729,6 +845,71 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Add(i.OutputRegister(0), base, Operand(offset.offset()));
break;
}
+ case kIeee754Float64Acos:
+ ASSEMBLE_IEEE754_UNOP(acos);
+ break;
+ case kIeee754Float64Acosh:
+ ASSEMBLE_IEEE754_UNOP(acosh);
+ break;
+ case kIeee754Float64Asin:
+ ASSEMBLE_IEEE754_UNOP(asin);
+ break;
+ case kIeee754Float64Asinh:
+ ASSEMBLE_IEEE754_UNOP(asinh);
+ break;
+ case kIeee754Float64Atan:
+ ASSEMBLE_IEEE754_UNOP(atan);
+ break;
+ case kIeee754Float64Atanh:
+ ASSEMBLE_IEEE754_UNOP(atanh);
+ break;
+ case kIeee754Float64Atan2:
+ ASSEMBLE_IEEE754_BINOP(atan2);
+ break;
+ case kIeee754Float64Cos:
+ ASSEMBLE_IEEE754_UNOP(cos);
+ break;
+ case kIeee754Float64Cosh:
+ ASSEMBLE_IEEE754_UNOP(cosh);
+ break;
+ case kIeee754Float64Cbrt:
+ ASSEMBLE_IEEE754_UNOP(cbrt);
+ break;
+ case kIeee754Float64Exp:
+ ASSEMBLE_IEEE754_UNOP(exp);
+ break;
+ case kIeee754Float64Expm1:
+ ASSEMBLE_IEEE754_UNOP(expm1);
+ break;
+ case kIeee754Float64Log:
+ ASSEMBLE_IEEE754_UNOP(log);
+ break;
+ case kIeee754Float64Log1p:
+ ASSEMBLE_IEEE754_UNOP(log1p);
+ break;
+ case kIeee754Float64Log2:
+ ASSEMBLE_IEEE754_UNOP(log2);
+ break;
+ case kIeee754Float64Log10:
+ ASSEMBLE_IEEE754_UNOP(log10);
+ break;
+ case kIeee754Float64Pow: {
+ MathPowStub stub(isolate(), MathPowStub::DOUBLE);
+ __ CallStub(&stub);
+ break;
+ }
+ case kIeee754Float64Sin:
+ ASSEMBLE_IEEE754_UNOP(sin);
+ break;
+ case kIeee754Float64Sinh:
+ ASSEMBLE_IEEE754_UNOP(sinh);
+ break;
+ case kIeee754Float64Tan:
+ ASSEMBLE_IEEE754_UNOP(tan);
+ break;
+ case kIeee754Float64Tanh:
+ ASSEMBLE_IEEE754_UNOP(tanh);
+ break;
case kArm64Float32RoundDown:
__ Frintm(i.OutputFloat32Register(), i.InputFloat32Register(0));
break;
@@ -775,12 +956,34 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
}
break;
case kArm64And:
- __ And(i.OutputRegister(), i.InputOrZeroRegister64(0),
- i.InputOperand2_64(1));
+ if (FlagsModeField::decode(opcode) != kFlags_none) {
+ // The ands instruction only sets N and Z, so only the following
+ // conditions make sense.
+ DCHECK(FlagsConditionField::decode(opcode) == kEqual ||
+ FlagsConditionField::decode(opcode) == kNotEqual ||
+ FlagsConditionField::decode(opcode) == kPositiveOrZero ||
+ FlagsConditionField::decode(opcode) == kNegative);
+ __ Ands(i.OutputRegister(), i.InputOrZeroRegister64(0),
+ i.InputOperand2_64(1));
+ } else {
+ __ And(i.OutputRegister(), i.InputOrZeroRegister64(0),
+ i.InputOperand2_64(1));
+ }
break;
case kArm64And32:
- __ And(i.OutputRegister32(), i.InputOrZeroRegister32(0),
- i.InputOperand2_32(1));
+ if (FlagsModeField::decode(opcode) != kFlags_none) {
+ // The ands instruction only sets N and Z, so only the following
+ // conditions make sense.
+ DCHECK(FlagsConditionField::decode(opcode) == kEqual ||
+ FlagsConditionField::decode(opcode) == kNotEqual ||
+ FlagsConditionField::decode(opcode) == kPositiveOrZero ||
+ FlagsConditionField::decode(opcode) == kNegative);
+ __ Ands(i.OutputRegister32(), i.InputOrZeroRegister32(0),
+ i.InputOperand2_32(1));
+ } else {
+ __ And(i.OutputRegister32(), i.InputOrZeroRegister32(0),
+ i.InputOperand2_32(1));
+ }
break;
case kArm64Bic:
__ Bic(i.OutputRegister(), i.InputOrZeroRegister64(0),
@@ -983,6 +1186,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
// Pseudo instructions turned into tbz/tbnz in AssembleArchBranch.
break;
case kArm64CompareAndBranch32:
+ case kArm64CompareAndBranch:
// Pseudo instruction turned into cbz/cbnz in AssembleArchBranch.
break;
case kArm64ClaimCSP: {
@@ -1038,7 +1242,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
Register prev = __ StackPointer();
__ SetStackPointer(arch_opcode == kArm64PokeCSP ? csp : jssp);
Operand operand(i.InputInt32(1) * kPointerSize);
- if (instr->InputAt(0)->IsDoubleRegister()) {
+ if (instr->InputAt(0)->IsFPRegister()) {
__ Poke(i.InputFloat64Register(0), operand);
} else {
__ Poke(i.InputRegister(0), operand);
@@ -1048,7 +1252,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
}
case kArm64PokePair: {
int slot = i.InputInt32(2) - 1;
- if (instr->InputAt(0)->IsDoubleRegister()) {
+ if (instr->InputAt(0)->IsFPRegister()) {
__ PokePair(i.InputFloat64Register(1), i.InputFloat64Register(0),
slot * kPointerSize);
} else {
@@ -1070,25 +1274,25 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Rbit(i.OutputRegister32(), i.InputRegister32(0));
break;
case kArm64Cmp:
- __ Cmp(i.InputOrZeroRegister64(0), i.InputOperand(1));
+ __ Cmp(i.InputOrZeroRegister64(0), i.InputOperand2_64(1));
break;
case kArm64Cmp32:
__ Cmp(i.InputOrZeroRegister32(0), i.InputOperand2_32(1));
break;
case kArm64Cmn:
- __ Cmn(i.InputOrZeroRegister64(0), i.InputOperand(1));
+ __ Cmn(i.InputOrZeroRegister64(0), i.InputOperand2_64(1));
break;
case kArm64Cmn32:
__ Cmn(i.InputOrZeroRegister32(0), i.InputOperand2_32(1));
break;
case kArm64Tst:
- __ Tst(i.InputRegister(0), i.InputOperand(1));
+ __ Tst(i.InputOrZeroRegister64(0), i.InputOperand(1));
break;
case kArm64Tst32:
- __ Tst(i.InputRegister32(0), i.InputOperand32(1));
+ __ Tst(i.InputOrZeroRegister32(0), i.InputOperand32(1));
break;
case kArm64Float32Cmp:
- if (instr->InputAt(1)->IsDoubleRegister()) {
+ if (instr->InputAt(1)->IsFPRegister()) {
__ Fcmp(i.InputFloat32Register(0), i.InputFloat32Register(1));
} else {
DCHECK(instr->InputAt(1)->IsImmediate());
@@ -1113,26 +1317,17 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Fdiv(i.OutputFloat32Register(), i.InputFloat32Register(0),
i.InputFloat32Register(1));
break;
- case kArm64Float32Max:
- // (b < a) ? a : b
- __ Fcmp(i.InputFloat32Register(1), i.InputFloat32Register(0));
- __ Fcsel(i.OutputFloat32Register(), i.InputFloat32Register(0),
- i.InputFloat32Register(1), lo);
- break;
- case kArm64Float32Min:
- // (a < b) ? a : b
- __ Fcmp(i.InputFloat32Register(0), i.InputFloat32Register(1));
- __ Fcsel(i.OutputFloat32Register(), i.InputFloat32Register(0),
- i.InputFloat32Register(1), lo);
- break;
case kArm64Float32Abs:
__ Fabs(i.OutputFloat32Register(), i.InputFloat32Register(0));
break;
+ case kArm64Float32Neg:
+ __ Fneg(i.OutputFloat32Register(), i.InputFloat32Register(0));
+ break;
case kArm64Float32Sqrt:
__ Fsqrt(i.OutputFloat32Register(), i.InputFloat32Register(0));
break;
case kArm64Float64Cmp:
- if (instr->InputAt(1)->IsDoubleRegister()) {
+ if (instr->InputAt(1)->IsFPRegister()) {
__ Fcmp(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
} else {
DCHECK(instr->InputAt(1)->IsImmediate());
@@ -1168,18 +1363,26 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
0, 2);
break;
}
- case kArm64Float64Max:
- // (b < a) ? a : b
- __ Fcmp(i.InputDoubleRegister(1), i.InputDoubleRegister(0));
- __ Fcsel(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
- i.InputDoubleRegister(1), lo);
- break;
- case kArm64Float64Min:
- // (a < b) ? a : b
- __ Fcmp(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
- __ Fcsel(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
- i.InputDoubleRegister(1), lo);
+ case kArm64Float32Max: {
+ __ Fmax(i.OutputFloat32Register(), i.InputFloat32Register(0),
+ i.InputFloat32Register(1));
+ break;
+ }
+ case kArm64Float64Max: {
+ __ Fmax(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+ i.InputDoubleRegister(1));
+ break;
+ }
+ case kArm64Float32Min: {
+ __ Fmin(i.OutputFloat32Register(), i.InputFloat32Register(0),
+ i.InputFloat32Register(1));
+ break;
+ }
+ case kArm64Float64Min: {
+ __ Fmin(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
+ i.InputDoubleRegister(1));
break;
+ }
case kArm64Float64Abs:
__ Fabs(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
@@ -1197,12 +1400,21 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
case kArm64Float32ToInt32:
__ Fcvtzs(i.OutputRegister32(), i.InputFloat32Register(0));
+ // Avoid INT32_MAX as an overflow indicator and use INT32_MIN instead,
+ // because INT32_MIN allows easier out-of-bounds detection.
+ __ Cmn(i.OutputRegister32(), 1);
+ __ Csinc(i.OutputRegister32(), i.OutputRegister32(), i.OutputRegister32(),
+ vc);
break;
case kArm64Float64ToInt32:
__ Fcvtzs(i.OutputRegister32(), i.InputDoubleRegister(0));
break;
case kArm64Float32ToUint32:
__ Fcvtzu(i.OutputRegister32(), i.InputFloat32Register(0));
+ // Avoid UINT32_MAX as an overflow indicator and use 0 instead,
+ // because 0 allows easier out-of-bounds detection.
+ __ Cmn(i.OutputRegister32(), 1);
+ __ Adc(i.OutputRegister32(), i.OutputRegister32(), Operand(0));
break;
case kArm64Float64ToUint32:
__ Fcvtzu(i.OutputRegister32(), i.InputDoubleRegister(0));
@@ -1305,6 +1517,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArm64Float64MoveU64:
__ Fmov(i.OutputFloat64Register(), i.InputRegister(0));
break;
+ case kArm64Float64SilenceNaN:
+ __ CanonicalizeNaN(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
+ break;
case kArm64U64MoveFloat64:
__ Fmov(i.OutputRegister(), i.InputDoubleRegister(0));
break;
@@ -1315,7 +1530,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Ldrsb(i.OutputRegister(), i.MemoryOperand());
break;
case kArm64Strb:
- __ Strb(i.InputRegister(2), i.MemoryOperand());
+ __ Strb(i.InputOrZeroRegister64(0), i.MemoryOperand(1));
break;
case kArm64Ldrh:
__ Ldrh(i.OutputRegister(), i.MemoryOperand());
@@ -1324,31 +1539,34 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Ldrsh(i.OutputRegister(), i.MemoryOperand());
break;
case kArm64Strh:
- __ Strh(i.InputRegister(2), i.MemoryOperand());
+ __ Strh(i.InputOrZeroRegister64(0), i.MemoryOperand(1));
+ break;
+ case kArm64Ldrsw:
+ __ Ldrsw(i.OutputRegister(), i.MemoryOperand());
break;
case kArm64LdrW:
__ Ldr(i.OutputRegister32(), i.MemoryOperand());
break;
case kArm64StrW:
- __ Str(i.InputRegister32(2), i.MemoryOperand());
+ __ Str(i.InputOrZeroRegister32(0), i.MemoryOperand(1));
break;
case kArm64Ldr:
__ Ldr(i.OutputRegister(), i.MemoryOperand());
break;
case kArm64Str:
- __ Str(i.InputRegister(2), i.MemoryOperand());
+ __ Str(i.InputOrZeroRegister64(0), i.MemoryOperand(1));
break;
case kArm64LdrS:
__ Ldr(i.OutputDoubleRegister().S(), i.MemoryOperand());
break;
case kArm64StrS:
- __ Str(i.InputDoubleRegister(2).S(), i.MemoryOperand());
+ __ Str(i.InputFloat32OrZeroRegister(0), i.MemoryOperand(1));
break;
case kArm64LdrD:
__ Ldr(i.OutputDoubleRegister(), i.MemoryOperand());
break;
case kArm64StrD:
- __ Str(i.InputDoubleRegister(2), i.MemoryOperand());
+ __ Str(i.InputFloat64OrZeroRegister(0), i.MemoryOperand(1));
break;
case kCheckedLoadInt8:
ASSEMBLE_CHECKED_LOAD_INTEGER(Ldrsb);
@@ -1392,7 +1610,37 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kCheckedStoreFloat64:
ASSEMBLE_CHECKED_STORE_FLOAT(64);
break;
+ case kAtomicLoadInt8:
+ ASSEMBLE_ATOMIC_LOAD_INTEGER(Ldrsb);
+ break;
+ case kAtomicLoadUint8:
+ ASSEMBLE_ATOMIC_LOAD_INTEGER(Ldrb);
+ break;
+ case kAtomicLoadInt16:
+ ASSEMBLE_ATOMIC_LOAD_INTEGER(Ldrsh);
+ break;
+ case kAtomicLoadUint16:
+ ASSEMBLE_ATOMIC_LOAD_INTEGER(Ldrh);
+ break;
+ case kAtomicLoadWord32:
+ __ Ldr(i.OutputRegister32(),
+ MemOperand(i.InputRegister(0), i.InputRegister(1)));
+ __ Dmb(InnerShareable, BarrierAll);
+ break;
+ case kAtomicStoreWord8:
+ ASSEMBLE_ATOMIC_STORE_INTEGER(Strb);
+ break;
+ case kAtomicStoreWord16:
+ ASSEMBLE_ATOMIC_STORE_INTEGER(Strh);
+ break;
+ case kAtomicStoreWord32:
+ __ Dmb(InnerShareable, BarrierAll);
+ __ Str(i.InputRegister32(2),
+ MemOperand(i.InputRegister(0), i.InputRegister(1)));
+ __ Dmb(InnerShareable, BarrierAll);
+ break;
}
+ return kSuccess;
} // NOLINT(readability/fn_size)
@@ -1415,6 +1663,17 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
default:
UNREACHABLE();
}
+ } else if (opcode == kArm64CompareAndBranch) {
+ switch (condition) {
+ case kEqual:
+ __ Cbz(i.InputRegister64(0), tlabel);
+ break;
+ case kNotEqual:
+ __ Cbnz(i.InputRegister64(0), tlabel);
+ break;
+ default:
+ UNREACHABLE();
+ }
} else if (opcode == kArm64TestAndBranch32) {
switch (condition) {
case kEqual:
@@ -1495,30 +1754,52 @@ void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
__ EndBlockPools();
}
-
-void CodeGenerator::AssembleDeoptimizerCall(
+CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
isolate(), deoptimization_id, bailout_type);
+ if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
+ DeoptimizeReason deoptimization_reason =
+ GetDeoptimizationReason(deoptimization_id);
+ __ RecordDeoptReason(deoptimization_reason, 0, deoptimization_id);
__ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
+ return kSuccess;
}
-void CodeGenerator::AssembleSetupStackPointer() {
- const CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
+void CodeGenerator::FinishFrame(Frame* frame) {
+ frame->AlignFrame(16);
+ CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
+
if (descriptor->UseNativeStack() || descriptor->IsCFunctionCall()) {
__ SetStackPointer(csp);
} else {
__ SetStackPointer(jssp);
}
+
+ // Save FP registers.
+ CPURegList saves_fp = CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
+ descriptor->CalleeSavedFPRegisters());
+ int saved_count = saves_fp.Count();
+ if (saved_count != 0) {
+ DCHECK(saves_fp.list() == CPURegList::GetCalleeSavedFP().list());
+ frame->AllocateSavedCalleeRegisterSlots(saved_count *
+ (kDoubleSize / kPointerSize));
+ }
+
+ CPURegList saves = CPURegList(CPURegister::kRegister, kXRegSizeInBits,
+ descriptor->CalleeSavedRegisters());
+ saved_count = saves.Count();
+ if (saved_count != 0) {
+ frame->AllocateSavedCalleeRegisterSlots(saved_count);
+ }
}
-void CodeGenerator::AssemblePrologue() {
+void CodeGenerator::AssembleConstructFrame() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
if (descriptor->UseNativeStack()) {
__ AssertCspAligned();
}
- int stack_shrink_slots = frame()->GetSpillSlotCount();
if (frame_access_state()->has_frame()) {
if (descriptor->IsJSFunctionCall()) {
DCHECK(!descriptor->UseNativeStack());
@@ -1527,14 +1808,20 @@ void CodeGenerator::AssemblePrologue() {
if (descriptor->IsCFunctionCall()) {
__ Push(lr, fp);
__ Mov(fp, masm_.StackPointer());
- __ Claim(stack_shrink_slots);
+ __ Claim(frame()->GetSpillSlotCount());
} else {
__ StubPrologue(info()->GetOutputStackFrameType(),
frame()->GetTotalFrameSlotCount());
}
}
+
+ if (!info()->GeneratePreagedPrologue()) {
+ unwinding_info_writer_.MarkFrameConstructed(__ pc_offset());
+ }
}
+ int shrink_slots = frame()->GetSpillSlotCount();
+
if (info()->is_osr()) {
// TurboFan OSR-compiled functions cannot be entered directly.
__ Abort(kShouldNotDirectlyEnterOsrFunction);
@@ -1545,11 +1832,11 @@ void CodeGenerator::AssemblePrologue() {
// remaining stack slots.
if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
osr_pc_offset_ = __ pc_offset();
- stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
+ shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
}
if (descriptor->IsJSFunctionCall()) {
- __ Claim(stack_shrink_slots);
+ __ Claim(shrink_slots);
}
// Save FP registers.
@@ -1559,8 +1846,6 @@ void CodeGenerator::AssemblePrologue() {
if (saved_count != 0) {
DCHECK(saves_fp.list() == CPURegList::GetCalleeSavedFP().list());
__ PushCPURegList(saves_fp);
- frame()->AllocateSavedCalleeRegisterSlots(saved_count *
- (kDoubleSize / kPointerSize));
}
// Save registers.
// TODO(palfia): TF save list is not in sync with
@@ -1571,7 +1856,6 @@ void CodeGenerator::AssemblePrologue() {
saved_count = saves.Count();
if (saved_count != 0) {
__ PushCPURegList(saves);
- frame()->AllocateSavedCalleeRegisterSlots(saved_count);
}
}
@@ -1593,6 +1877,8 @@ void CodeGenerator::AssembleReturn() {
__ PopCPURegList(saves_fp);
}
+ unwinding_info_writer_.MarkBlockWillExit();
+
int pop_count = static_cast<int>(descriptor->StackParameterCount());
if (descriptor->IsCFunctionCall()) {
AssembleDeconstructFrame();
@@ -1668,11 +1954,11 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
__ Str(dst, g.ToMemOperand(destination, masm()));
}
} else if (src.type() == Constant::kFloat32) {
- if (destination->IsDoubleRegister()) {
+ if (destination->IsFPRegister()) {
FPRegister dst = g.ToDoubleRegister(destination).S();
__ Fmov(dst, src.ToFloat32());
} else {
- DCHECK(destination->IsDoubleStackSlot());
+ DCHECK(destination->IsFPStackSlot());
UseScratchRegisterScope scope(masm());
FPRegister temp = scope.AcquireS();
__ Fmov(temp, src.ToFloat32());
@@ -1680,30 +1966,30 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
}
} else {
DCHECK_EQ(Constant::kFloat64, src.type());
- if (destination->IsDoubleRegister()) {
+ if (destination->IsFPRegister()) {
FPRegister dst = g.ToDoubleRegister(destination);
__ Fmov(dst, src.ToFloat64());
} else {
- DCHECK(destination->IsDoubleStackSlot());
+ DCHECK(destination->IsFPStackSlot());
UseScratchRegisterScope scope(masm());
FPRegister temp = scope.AcquireD();
__ Fmov(temp, src.ToFloat64());
__ Str(temp, g.ToMemOperand(destination, masm()));
}
}
- } else if (source->IsDoubleRegister()) {
+ } else if (source->IsFPRegister()) {
FPRegister src = g.ToDoubleRegister(source);
- if (destination->IsDoubleRegister()) {
+ if (destination->IsFPRegister()) {
FPRegister dst = g.ToDoubleRegister(destination);
__ Fmov(dst, src);
} else {
- DCHECK(destination->IsDoubleStackSlot());
+ DCHECK(destination->IsFPStackSlot());
__ Str(src, g.ToMemOperand(destination, masm()));
}
- } else if (source->IsDoubleStackSlot()) {
- DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
+ } else if (source->IsFPStackSlot()) {
+ DCHECK(destination->IsFPRegister() || destination->IsFPStackSlot());
MemOperand src = g.ToMemOperand(source, masm());
- if (destination->IsDoubleRegister()) {
+ if (destination->IsFPRegister()) {
__ Ldr(g.ToDoubleRegister(destination), src);
} else {
UseScratchRegisterScope scope(masm());
@@ -1739,7 +2025,7 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source,
__ Ldr(src, dst);
__ Str(temp, dst);
}
- } else if (source->IsStackSlot() || source->IsDoubleStackSlot()) {
+ } else if (source->IsStackSlot() || source->IsFPStackSlot()) {
UseScratchRegisterScope scope(masm());
DoubleRegister temp_0 = scope.AcquireD();
DoubleRegister temp_1 = scope.AcquireD();
@@ -1749,17 +2035,17 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source,
__ Ldr(temp_1, dst);
__ Str(temp_0, dst);
__ Str(temp_1, src);
- } else if (source->IsDoubleRegister()) {
+ } else if (source->IsFPRegister()) {
UseScratchRegisterScope scope(masm());
FPRegister temp = scope.AcquireD();
FPRegister src = g.ToDoubleRegister(source);
- if (destination->IsDoubleRegister()) {
+ if (destination->IsFPRegister()) {
FPRegister dst = g.ToDoubleRegister(destination);
__ Fmov(temp, src);
__ Fmov(src, dst);
__ Fmov(dst, temp);
} else {
- DCHECK(destination->IsDoubleStackSlot());
+ DCHECK(destination->IsFPStackSlot());
MemOperand dst = g.ToMemOperand(destination, masm());
__ Fmov(temp, src);
__ Ldr(src, dst);
@@ -1778,9 +2064,6 @@ void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) {
}
-void CodeGenerator::AddNopForSmiCodeInlining() { __ movz(xzr, 0); }
-
-
void CodeGenerator::EnsureSpaceForLazyDeopt() {
if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
return;