diff options
author | Michaël Zasso <targos@protonmail.com> | 2018-03-07 08:54:53 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2018-03-07 16:48:52 +0100 |
commit | 88786fecff336342a56e6f2e7ff3b286be716e47 (patch) | |
tree | 92e6ba5b8ac8dae1a058988d20c9d27bfa654390 /deps/v8/src/compiler/arm | |
parent | 4e86f9b5ab83cbabf43839385bf383e6a7ef7d19 (diff) | |
download | node-new-88786fecff336342a56e6f2e7ff3b286be716e47.tar.gz |
deps: update V8 to 6.5.254.31
PR-URL: https://github.com/nodejs/node/pull/18453
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Yang Guo <yangguo@chromium.org>
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Diffstat (limited to 'deps/v8/src/compiler/arm')
-rw-r--r-- | deps/v8/src/compiler/arm/code-generator-arm.cc | 325 | ||||
-rw-r--r-- | deps/v8/src/compiler/arm/instruction-codes-arm.h | 1 | ||||
-rw-r--r-- | deps/v8/src/compiler/arm/instruction-scheduler-arm.cc | 1 | ||||
-rw-r--r-- | deps/v8/src/compiler/arm/instruction-selector-arm.cc | 181 |
4 files changed, 178 insertions, 330 deletions
diff --git a/deps/v8/src/compiler/arm/code-generator-arm.cc b/deps/v8/src/compiler/arm/code-generator-arm.cc index 1a66e5b7d4..a238cf29d4 100644 --- a/deps/v8/src/compiler/arm/code-generator-arm.cc +++ b/deps/v8/src/compiler/arm/code-generator-arm.cc @@ -152,49 +152,6 @@ class ArmOperandConverter final : public InstructionOperandConverter { namespace { -class OutOfLineLoadFloat final : public OutOfLineCode { - public: - OutOfLineLoadFloat(CodeGenerator* gen, SwVfpRegister result) - : OutOfLineCode(gen), result_(result) {} - - void Generate() final { - // Compute sqrtf(-1.0f), which results in a quiet single-precision NaN. - __ vmov(result_, Float32(-1.0f)); - __ vsqrt(result_, result_); - } - - private: - SwVfpRegister const result_; -}; - -class OutOfLineLoadDouble final : public OutOfLineCode { - public: - OutOfLineLoadDouble(CodeGenerator* gen, DwVfpRegister result) - : OutOfLineCode(gen), result_(result) {} - - void Generate() final { - // Compute sqrt(-1.0), which results in a quiet double-precision NaN. - __ vmov(result_, Double(-1.0)); - __ vsqrt(result_, result_); - } - - private: - DwVfpRegister const result_; -}; - - -class OutOfLineLoadInteger final : public OutOfLineCode { - public: - OutOfLineLoadInteger(CodeGenerator* gen, Register result) - : OutOfLineCode(gen), result_(result) {} - - void Generate() final { __ mov(result_, Operand::Zero()); } - - private: - Register const result_; -}; - - class OutOfLineRecordWrite final : public OutOfLineCode { public: OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register index, @@ -359,64 +316,6 @@ Condition FlagsConditionToCondition(FlagsCondition condition) { } // namespace -#define ASSEMBLE_CHECKED_LOAD_FP(Type) \ - do { \ - auto result = i.Output##Type##Register(); \ - auto offset = i.InputRegister(0); \ - if (instr->InputAt(1)->IsRegister()) { \ - __ cmp(offset, i.InputRegister(1)); \ - } else { \ - __ cmp(offset, i.InputImmediate(1)); \ - } \ - auto ool = new (zone()) OutOfLineLoad##Type(this, result); \ - __ b(hs, ool->entry()); \ - __ vldr(result, i.InputOffset(2)); \ - __ bind(ool->exit()); \ - DCHECK_EQ(LeaveCC, i.OutputSBit()); \ - } while (0) - -#define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ - do { \ - auto result = i.OutputRegister(); \ - auto offset = i.InputRegister(0); \ - if (instr->InputAt(1)->IsRegister()) { \ - __ cmp(offset, i.InputRegister(1)); \ - } else { \ - __ cmp(offset, i.InputImmediate(1)); \ - } \ - auto ool = new (zone()) OutOfLineLoadInteger(this, result); \ - __ b(hs, ool->entry()); \ - __ asm_instr(result, i.InputOffset(2)); \ - __ bind(ool->exit()); \ - DCHECK_EQ(LeaveCC, i.OutputSBit()); \ - } while (0) - -#define ASSEMBLE_CHECKED_STORE_FP(Type) \ - do { \ - auto offset = i.InputRegister(0); \ - if (instr->InputAt(1)->IsRegister()) { \ - __ cmp(offset, i.InputRegister(1)); \ - } else { \ - __ cmp(offset, i.InputImmediate(1)); \ - } \ - auto value = i.Input##Type##Register(2); \ - __ vstr(value, i.InputOffset(3), lo); \ - DCHECK_EQ(LeaveCC, i.OutputSBit()); \ - } while (0) - -#define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ - do { \ - auto offset = i.InputRegister(0); \ - if (instr->InputAt(1)->IsRegister()) { \ - __ cmp(offset, i.InputRegister(1)); \ - } else { \ - __ cmp(offset, i.InputImmediate(1)); \ - } \ - auto value = i.InputRegister(2); \ - __ asm_instr(value, i.InputOffset(3), lo); \ - DCHECK_EQ(LeaveCC, i.OutputSBit()); \ - } while (0) - #define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr) \ do { \ __ asm_instr(i.OutputRegister(), \ @@ -432,51 +331,51 @@ Condition FlagsConditionToCondition(FlagsCondition condition) { __ dmb(ISH); \ } while (0) -#define ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(load_instr, store_instr) \ - do { \ - Label exchange; \ - __ add(i.InputRegister(0), i.InputRegister(0), i.InputRegister(1)); \ - __ dmb(ISH); \ - __ bind(&exchange); \ - __ load_instr(i.OutputRegister(0), i.InputRegister(0)); \ - __ store_instr(i.TempRegister(0), i.InputRegister(2), i.InputRegister(0)); \ - __ teq(i.TempRegister(0), Operand(0)); \ - __ b(ne, &exchange); \ - __ dmb(ISH); \ - } while (0) - -#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(load_instr, store_instr) \ - do { \ - Label compareExchange; \ - Label exit; \ - __ add(i.InputRegister(0), i.InputRegister(0), i.InputRegister(1)); \ - __ dmb(ISH); \ - __ bind(&compareExchange); \ - __ load_instr(i.OutputRegister(0), i.InputRegister(0)); \ - __ teq(i.InputRegister(2), Operand(i.OutputRegister(0))); \ - __ b(ne, &exit); \ - __ store_instr(i.TempRegister(0), i.InputRegister(3), i.InputRegister(0)); \ - __ teq(i.TempRegister(0), Operand(0)); \ - __ b(ne, &compareExchange); \ - __ bind(&exit); \ - __ dmb(ISH); \ +#define ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(load_instr, store_instr) \ + do { \ + Label exchange; \ + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); \ + __ dmb(ISH); \ + __ bind(&exchange); \ + __ load_instr(i.OutputRegister(0), i.TempRegister(1)); \ + __ store_instr(i.TempRegister(0), i.InputRegister(2), i.TempRegister(1)); \ + __ teq(i.TempRegister(0), Operand(0)); \ + __ b(ne, &exchange); \ + __ dmb(ISH); \ } while (0) -#define ASSEMBLE_ATOMIC_BINOP(load_instr, store_instr, bin_instr) \ +#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(load_instr, store_instr, \ + cmp_reg) \ do { \ - Label binop; \ - __ add(i.InputRegister(0), i.InputRegister(0), i.InputRegister(1)); \ + Label compareExchange; \ + Label exit; \ __ dmb(ISH); \ - __ bind(&binop); \ - __ load_instr(i.OutputRegister(0), i.InputRegister(0)); \ - __ bin_instr(i.TempRegister(0), i.OutputRegister(0), \ - Operand(i.InputRegister(2))); \ - __ store_instr(i.TempRegister(1), i.TempRegister(0), i.InputRegister(0)); \ - __ teq(i.TempRegister(1), Operand(0)); \ - __ b(ne, &binop); \ + __ bind(&compareExchange); \ + __ load_instr(i.OutputRegister(0), i.TempRegister(1)); \ + __ teq(cmp_reg, Operand(i.OutputRegister(0))); \ + __ b(ne, &exit); \ + __ store_instr(i.TempRegister(0), i.InputRegister(3), i.TempRegister(1)); \ + __ teq(i.TempRegister(0), Operand(0)); \ + __ b(ne, &compareExchange); \ + __ bind(&exit); \ __ dmb(ISH); \ } while (0) +#define ASSEMBLE_ATOMIC_BINOP(load_instr, store_instr, bin_instr) \ + do { \ + Label binop; \ + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); \ + __ dmb(ISH); \ + __ bind(&binop); \ + __ load_instr(i.OutputRegister(0), i.TempRegister(1)); \ + __ bin_instr(i.TempRegister(0), i.OutputRegister(0), \ + Operand(i.InputRegister(2))); \ + __ store_instr(i.TempRegister(2), i.TempRegister(0), i.TempRegister(1)); \ + __ teq(i.TempRegister(2), Operand(0)); \ + __ b(ne, &binop); \ + __ dmb(ISH); \ + } while (0) + #define ASSEMBLE_IEEE754_BINOP(name) \ do { \ /* TODO(bmeurer): We should really get rid of this special instruction, */ \ @@ -675,17 +574,18 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr, // Check if the code object is marked for deoptimization. If it is, then it // jumps to the CompileLazyDeoptimizedCode builtin. In order to do this we need // to: -// 1. load the address of the current instruction; +// 1. compute the offset of the {CodeDataContainer} from our current location +// and load it. // 2. read from memory the word that contains that bit, which can be found in // the flags in the referenced {CodeDataContainer} object; // 3. test kMarkedForDeoptimizationBit in those flags; and // 4. if it is not zero then it jumps to the builtin. void CodeGenerator::BailoutIfDeoptimized() { int pc_offset = __ pc_offset(); - int offset = - Code::kCodeDataContainerOffset - (Code::kHeaderSize + pc_offset + 8); + int offset = Code::kCodeDataContainerOffset - + (Code::kHeaderSize + pc_offset + TurboAssembler::kPcLoadDelta); // We can use the register pc - 8 for the address of the current instruction. - __ ldr(ip, MemOperand(pc, offset)); + __ ldr_pcrel(ip, offset); __ ldr(ip, FieldMemOperand(ip, CodeDataContainer::kKindSpecificFlagsOffset)); __ tst(ip, Operand(1 << Code::kMarkedForDeoptimizationBit)); Handle<Code> code = isolate()->builtins()->builtin_handle( @@ -804,7 +704,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( // Check the function's context matches the context argument. __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); __ cmp(cp, kScratchReg); - __ Assert(eq, kWrongFunctionContext); + __ Assert(eq, AbortReason::kWrongFunctionContext); } __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeOffset)); __ add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); @@ -1681,13 +1581,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( case kArmPush: if (instr->InputAt(0)->IsFPRegister()) { LocationOperand* op = LocationOperand::cast(instr->InputAt(0)); - if (op->representation() == MachineRepresentation::kFloat64) { - __ vpush(i.InputDoubleRegister(0)); - frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize); - } else { - DCHECK_EQ(MachineRepresentation::kFloat32, op->representation()); - __ vpush(i.InputFloatRegister(0)); - frame_access_state()->IncreaseSPDelta(1); + switch (op->representation()) { + case MachineRepresentation::kFloat32: + __ vpush(i.InputFloatRegister(0)); + frame_access_state()->IncreaseSPDelta(1); + break; + case MachineRepresentation::kFloat64: + __ vpush(i.InputDoubleRegister(0)); + frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize); + break; + case MachineRepresentation::kSimd128: { + __ vpush(i.InputSimd128Register(0)); + frame_access_state()->IncreaseSPDelta(kSimd128Size / kPointerSize); + break; + } + default: + UNREACHABLE(); + break; } } else { __ push(i.InputRegister(0)); @@ -1701,6 +1611,24 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( DCHECK_EQ(LeaveCC, i.OutputSBit()); break; } + case kArmPeek: { + // The incoming value is 0-based, but we need a 1-based value. + int reverse_slot = i.InputInt32(0) + 1; + int offset = + FrameSlotToFPOffset(frame()->GetTotalFrameSlotCount() - reverse_slot); + if (instr->OutputAt(0)->IsFPRegister()) { + LocationOperand* op = LocationOperand::cast(instr->OutputAt(0)); + if (op->representation() == MachineRepresentation::kFloat64) { + __ vldr(i.OutputDoubleRegister(), MemOperand(fp, offset)); + } else { + DCHECK_EQ(MachineRepresentation::kFloat32, op->representation()); + __ vldr(i.OutputFloatRegister(), MemOperand(fp, offset)); + } + } else { + __ ldr(i.OutputRegister(), MemOperand(fp, offset)); + } + break; + } case kArmF32x4Splat: { int src_code = i.InputFloatRegister(0).code(); __ vdup(Neon32, i.OutputSimd128Register(), @@ -2558,47 +2486,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ ExtractLane(i.OutputRegister(), kScratchDoubleReg, NeonS8, 0); break; } - case kCheckedLoadInt8: - ASSEMBLE_CHECKED_LOAD_INTEGER(ldrsb); - break; - case kCheckedLoadUint8: - ASSEMBLE_CHECKED_LOAD_INTEGER(ldrb); - break; - case kCheckedLoadInt16: - ASSEMBLE_CHECKED_LOAD_INTEGER(ldrsh); - break; - case kCheckedLoadUint16: - ASSEMBLE_CHECKED_LOAD_INTEGER(ldrh); - break; - case kCheckedLoadWord32: - ASSEMBLE_CHECKED_LOAD_INTEGER(ldr); - break; - case kCheckedLoadFloat32: - ASSEMBLE_CHECKED_LOAD_FP(Float); - break; - case kCheckedLoadFloat64: - ASSEMBLE_CHECKED_LOAD_FP(Double); - break; - case kCheckedStoreWord8: - ASSEMBLE_CHECKED_STORE_INTEGER(strb); - break; - case kCheckedStoreWord16: - ASSEMBLE_CHECKED_STORE_INTEGER(strh); - break; - case kCheckedStoreWord32: - ASSEMBLE_CHECKED_STORE_INTEGER(str); - break; - case kCheckedStoreFloat32: - ASSEMBLE_CHECKED_STORE_FP(Float); - break; - case kCheckedStoreFloat64: - ASSEMBLE_CHECKED_STORE_FP(Double); - break; - case kCheckedLoadWord64: - case kCheckedStoreWord64: - UNREACHABLE(); // currently unsupported checked int64 load/store. - break; - case kAtomicLoadInt8: ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrsb); break; @@ -2642,25 +2529,35 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrex, strex); break; case kAtomicCompareExchangeInt8: - __ uxtb(i.InputRegister(2), i.InputRegister(2)); - ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb); + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); + __ uxtb(i.TempRegister(2), i.InputRegister(2)); + ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb, + i.TempRegister(2)); __ sxtb(i.OutputRegister(0), i.OutputRegister(0)); break; case kAtomicCompareExchangeUint8: - __ uxtb(i.InputRegister(2), i.InputRegister(2)); - ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb); + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); + __ uxtb(i.TempRegister(2), i.InputRegister(2)); + ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb, + i.TempRegister(2)); break; case kAtomicCompareExchangeInt16: - __ uxth(i.InputRegister(2), i.InputRegister(2)); - ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh); + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); + __ uxth(i.TempRegister(2), i.InputRegister(2)); + ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh, + i.TempRegister(2)); __ sxth(i.OutputRegister(0), i.OutputRegister(0)); break; case kAtomicCompareExchangeUint16: - __ uxth(i.InputRegister(2), i.InputRegister(2)); - ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh); + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); + __ uxth(i.TempRegister(2), i.InputRegister(2)); + ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh, + i.TempRegister(2)); break; case kAtomicCompareExchangeWord32: - ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrex, strex); + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); + ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrex, strex, + i.InputRegister(2)); break; #define ATOMIC_BINOP_CASE(op, inst) \ case kAtomic##op##Int8: \ @@ -2686,10 +2583,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ATOMIC_BINOP_CASE(Or, orr) ATOMIC_BINOP_CASE(Xor, eor) #undef ATOMIC_BINOP_CASE -#undef ASSEMBLE_CHECKED_LOAD_FP -#undef ASSEMBLE_CHECKED_LOAD_INTEGER -#undef ASSEMBLE_CHECKED_STORE_FP -#undef ASSEMBLE_CHECKED_STORE_INTEGER #undef ASSEMBLE_ATOMIC_LOAD_INTEGER #undef ASSEMBLE_ATOMIC_STORE_INTEGER #undef ASSEMBLE_ATOMIC_EXCHANGE_INTEGER @@ -2774,7 +2667,7 @@ void CodeGenerator::AssembleArchTrap(Instruction* instr, gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0, Safepoint::kNoLazyDeopt); if (FLAG_debug_code) { - __ stop(GetBailoutReason(kUnexpectedReturnFromWasmTrap)); + __ stop(GetAbortReason(AbortReason::kUnexpectedReturnFromWasmTrap)); } } } @@ -2878,7 +2771,7 @@ void CodeGenerator::AssembleConstructFrame() { if (info()->is_osr()) { // TurboFan OSR-compiled functions cannot be entered directly. - __ Abort(kShouldNotDirectlyEnterOsrFunction); + __ Abort(AbortReason::kShouldNotDirectlyEnterOsrFunction); // Unoptimized code jumps directly to this entrypoint while the unoptimized // frame is still on the stack. Optimized code uses OSR values directly from @@ -2929,15 +2822,16 @@ void CodeGenerator::AssembleConstructFrame() { RecordSafepoint(reference_map, Safepoint::kSimple, 0, Safepoint::kNoLazyDeopt); if (FLAG_debug_code) { - __ stop(GetBailoutReason(kUnexpectedReturnFromThrow)); + __ stop(GetAbortReason(AbortReason::kUnexpectedReturnFromThrow)); } __ bind(&done); } } - // Skip callee-saved slots, which are pushed below. + // Skip callee-saved and return slots, which are pushed below. shrink_slots -= base::bits::CountPopulation(saves); + shrink_slots -= frame()->GetReturnSlotCount(); shrink_slots -= 2 * base::bits::CountPopulation(saves_fp); if (shrink_slots > 0) { __ sub(sp, sp, Operand(shrink_slots * kPointerSize)); @@ -2953,16 +2847,29 @@ void CodeGenerator::AssembleConstructFrame() { __ vstm(db_w, sp, DwVfpRegister::from_code(first), DwVfpRegister::from_code(last)); } + if (saves != 0) { // Save callee-saved registers. __ stm(db_w, sp, saves); } + + const int returns = frame()->GetReturnSlotCount(); + if (returns != 0) { + // Create space for returns. + __ sub(sp, sp, Operand(returns * kPointerSize)); + } } void CodeGenerator::AssembleReturn(InstructionOperand* pop) { CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); int pop_count = static_cast<int>(descriptor->StackParameterCount()); + const int returns = frame()->GetReturnSlotCount(); + if (returns != 0) { + // Free space of returns. + __ add(sp, sp, Operand(returns * kPointerSize)); + } + // Restore registers. const RegList saves = descriptor->CalleeSavedRegisters(); if (saves != 0) { diff --git a/deps/v8/src/compiler/arm/instruction-codes-arm.h b/deps/v8/src/compiler/arm/instruction-codes-arm.h index c839d25cab..a7cf80450a 100644 --- a/deps/v8/src/compiler/arm/instruction-codes-arm.h +++ b/deps/v8/src/compiler/arm/instruction-codes-arm.h @@ -124,6 +124,7 @@ namespace compiler { V(ArmStr) \ V(ArmPush) \ V(ArmPoke) \ + V(ArmPeek) \ V(ArmF32x4Splat) \ V(ArmF32x4ExtractLane) \ V(ArmF32x4ReplaceLane) \ diff --git a/deps/v8/src/compiler/arm/instruction-scheduler-arm.cc b/deps/v8/src/compiler/arm/instruction-scheduler-arm.cc index 0092a9dbe5..a592515179 100644 --- a/deps/v8/src/compiler/arm/instruction-scheduler-arm.cc +++ b/deps/v8/src/compiler/arm/instruction-scheduler-arm.cc @@ -262,6 +262,7 @@ int InstructionScheduler::GetTargetInstructionFlags( case kArmLdrh: case kArmLdrsh: case kArmLdr: + case kArmPeek: return kIsLoadOperation; case kArmVstrF32: diff --git a/deps/v8/src/compiler/arm/instruction-selector-arm.cc b/deps/v8/src/compiler/arm/instruction-selector-arm.cc index 4ded82fa5b..f94d114d07 100644 --- a/deps/v8/src/compiler/arm/instruction-selector-arm.cc +++ b/deps/v8/src/compiler/arm/instruction-selector-arm.cc @@ -300,7 +300,8 @@ void VisitBinop(InstructionSelector* selector, Node* node, opcode = cont->Encode(opcode); if (cont->IsDeoptimize()) { selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, - cont->kind(), cont->reason(), cont->frame_state()); + cont->kind(), cont->reason(), cont->feedback(), + cont->frame_state()); } else if (cont->IsTrap()) { inputs[input_count++] = g.UseImmediate(cont->trap_id()); selector->Emit(opcode, output_count, outputs, input_count, inputs); @@ -721,93 +722,6 @@ void InstructionSelector::VisitUnalignedStore(Node* node) { } } -void InstructionSelector::VisitCheckedLoad(Node* node) { - CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op()); - ArmOperandGenerator g(this); - Node* const buffer = node->InputAt(0); - Node* const offset = node->InputAt(1); - Node* const length = node->InputAt(2); - ArchOpcode opcode = kArchNop; - switch (load_rep.representation()) { - case MachineRepresentation::kWord8: - opcode = load_rep.IsSigned() ? kCheckedLoadInt8 : kCheckedLoadUint8; - break; - case MachineRepresentation::kWord16: - opcode = load_rep.IsSigned() ? kCheckedLoadInt16 : kCheckedLoadUint16; - break; - case MachineRepresentation::kWord32: - opcode = kCheckedLoadWord32; - break; - case MachineRepresentation::kFloat32: - opcode = kCheckedLoadFloat32; - break; - case MachineRepresentation::kFloat64: - opcode = kCheckedLoadFloat64; - break; - case MachineRepresentation::kBit: // Fall through. - case MachineRepresentation::kTaggedSigned: // Fall through. - case MachineRepresentation::kTaggedPointer: // Fall through. - case MachineRepresentation::kTagged: // Fall through. - case MachineRepresentation::kWord64: // Fall through. - case MachineRepresentation::kSimd128: // Fall through. - case MachineRepresentation::kNone: - UNREACHABLE(); - return; - } - InstructionOperand offset_operand = g.UseRegister(offset); - InstructionOperand length_operand = g.CanBeImmediate(length, kArmCmp) - ? g.UseImmediate(length) - : g.UseRegister(length); - Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), - g.DefineAsRegister(node), offset_operand, length_operand, - g.UseRegister(buffer), offset_operand); -} - - -void InstructionSelector::VisitCheckedStore(Node* node) { - MachineRepresentation rep = CheckedStoreRepresentationOf(node->op()); - ArmOperandGenerator g(this); - Node* const buffer = node->InputAt(0); - Node* const offset = node->InputAt(1); - Node* const length = node->InputAt(2); - Node* const value = node->InputAt(3); - ArchOpcode opcode = kArchNop; - switch (rep) { - case MachineRepresentation::kWord8: - opcode = kCheckedStoreWord8; - break; - case MachineRepresentation::kWord16: - opcode = kCheckedStoreWord16; - break; - case MachineRepresentation::kWord32: - opcode = kCheckedStoreWord32; - break; - case MachineRepresentation::kFloat32: - opcode = kCheckedStoreFloat32; - break; - case MachineRepresentation::kFloat64: - opcode = kCheckedStoreFloat64; - break; - case MachineRepresentation::kBit: // Fall through. - case MachineRepresentation::kTaggedSigned: // Fall through. - case MachineRepresentation::kTaggedPointer: // Fall through. - case MachineRepresentation::kTagged: // Fall through. - case MachineRepresentation::kWord64: // Fall through. - case MachineRepresentation::kSimd128: // Fall through. - case MachineRepresentation::kNone: - UNREACHABLE(); - return; - } - InstructionOperand offset_operand = g.UseRegister(offset); - InstructionOperand length_operand = g.CanBeImmediate(length, kArmCmp) - ? g.UseImmediate(length) - : g.UseRegister(length); - Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), g.NoOutput(), - offset_operand, length_operand, g.UseRegister(value), - g.UseRegister(buffer), offset_operand); -} - - namespace { void EmitBic(InstructionSelector* selector, Node* node, Node* left, @@ -868,14 +782,14 @@ void InstructionSelector::VisitWord32And(Node* node) { uint32_t const shift = mshr.right().Value(); if (((shift == 8) || (shift == 16) || (shift == 24)) && - (value == 0xff)) { + (value == 0xFF)) { // Merge SHR into AND by emitting a UXTB instruction with a // bytewise rotation. Emit(kArmUxtb, g.DefineAsRegister(m.node()), g.UseRegister(mshr.left().node()), g.TempImmediate(mshr.right().Value())); return; - } else if (((shift == 8) || (shift == 16)) && (value == 0xffff)) { + } else if (((shift == 8) || (shift == 16)) && (value == 0xFFFF)) { // Merge SHR into AND by emitting a UXTH instruction with a // bytewise rotation. Emit(kArmUxth, g.DefineAsRegister(m.node()), @@ -897,9 +811,9 @@ void InstructionSelector::VisitWord32And(Node* node) { } } } - } else if (value == 0xffff) { + } else if (value == 0xFFFF) { // Emit UXTH for this AND. We don't bother testing for UXTB, as it's no - // better than AND 0xff for this operation. + // better than AND 0xFF for this operation. Emit(kArmUxth, g.DefineAsRegister(m.node()), g.UseRegister(m.left().node()), g.TempImmediate(0)); return; @@ -995,7 +909,8 @@ void VisitShift(InstructionSelector* selector, Node* node, opcode = cont->Encode(opcode); if (cont->IsDeoptimize()) { selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, - cont->kind(), cont->reason(), cont->frame_state()); + cont->kind(), cont->reason(), cont->feedback(), + cont->frame_state()); } else if (cont->IsTrap()) { inputs[input_count++] = g.UseImmediate(cont->trap_id()); selector->Emit(opcode, output_count, outputs, input_count, inputs); @@ -1206,6 +1121,7 @@ void InstructionSelector::VisitWord32ReverseBytes(Node* node) { UNREACHABLE(); } void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); } +void InstructionSelector::VisitSpeculationFence(Node* node) { UNREACHABLE(); } void InstructionSelector::VisitInt32Add(Node* node) { ArmOperandGenerator g(this); @@ -1230,12 +1146,12 @@ void InstructionSelector::VisitInt32Add(Node* node) { } case IrOpcode::kWord32And: { Int32BinopMatcher mleft(m.left().node()); - if (mleft.right().Is(0xff)) { + if (mleft.right().Is(0xFF)) { Emit(kArmUxtab, g.DefineAsRegister(node), g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()), g.TempImmediate(0)); return; - } else if (mleft.right().Is(0xffff)) { + } else if (mleft.right().Is(0xFFFF)) { Emit(kArmUxtah, g.DefineAsRegister(node), g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()), g.TempImmediate(0)); @@ -1284,12 +1200,12 @@ void InstructionSelector::VisitInt32Add(Node* node) { } case IrOpcode::kWord32And: { Int32BinopMatcher mright(m.right().node()); - if (mright.right().Is(0xff)) { + if (mright.right().Is(0xFF)) { Emit(kArmUxtab, g.DefineAsRegister(node), g.UseRegister(m.left().node()), g.UseRegister(mright.left().node()), g.TempImmediate(0)); return; - } else if (mright.right().Is(0xffff)) { + } else if (mright.right().Is(0xFFFF)) { Emit(kArmUxtah, g.DefineAsRegister(node), g.UseRegister(m.left().node()), g.UseRegister(mright.left().node()), g.TempImmediate(0)); @@ -1358,7 +1274,8 @@ void EmitInt32MulWithOverflow(InstructionSelector* selector, Node* node, } else if (cont->IsDeoptimize()) { InstructionOperand in[] = {temp_operand, result_operand, shift_31}; selector->EmitDeoptimize(opcode, 0, nullptr, 3, in, cont->kind(), - cont->reason(), cont->frame_state()); + cont->reason(), cont->feedback(), + cont->frame_state()); } else if (cont->IsSet()) { selector->Emit(opcode, g.DefineAsRegister(cont->result()), temp_operand, result_operand, shift_31); @@ -1596,22 +1513,44 @@ void InstructionSelector::EmitPrepareArguments( // Poke any stack arguments. for (size_t n = 0; n < arguments->size(); ++n) { PushParameter input = (*arguments)[n]; - if (input.node()) { + if (input.node) { int slot = static_cast<int>(n); Emit(kArmPoke | MiscField::encode(slot), g.NoOutput(), - g.UseRegister(input.node())); + g.UseRegister(input.node)); } } } else { // Push any stack arguments. for (PushParameter input : base::Reversed(*arguments)) { // Skip any alignment holes in pushed nodes. - if (input.node() == nullptr) continue; - Emit(kArmPush, g.NoOutput(), g.UseRegister(input.node())); + if (input.node == nullptr) continue; + Emit(kArmPush, g.NoOutput(), g.UseRegister(input.node)); } } } +void InstructionSelector::EmitPrepareResults(ZoneVector<PushParameter>* results, + const CallDescriptor* descriptor, + Node* node) { + ArmOperandGenerator g(this); + + int reverse_slot = 0; + for (PushParameter output : *results) { + if (!output.location.IsCallerFrameSlot()) continue; + // Skip any alignment holes in nodes. + if (output.node != nullptr) { + DCHECK(!descriptor->IsCFunctionCall()); + if (output.location.GetType() == MachineType::Float32()) { + MarkAsFloat32(output.node); + } else if (output.location.GetType() == MachineType::Float64()) { + MarkAsFloat64(output.node); + } + Emit(kArmPeek, g.DefineAsRegister(output.node), + g.UseImmediate(reverse_slot)); + } + reverse_slot += output.location.GetSizeInPointers(); + } +} bool InstructionSelector::IsTailCallAddressImmediate() { return false; } @@ -1630,7 +1569,8 @@ void VisitCompare(InstructionSelector* selector, InstructionCode opcode, g.Label(cont->true_block()), g.Label(cont->false_block())); } else if (cont->IsDeoptimize()) { selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, cont->kind(), - cont->reason(), cont->frame_state()); + cont->reason(), cont->feedback(), + cont->frame_state()); } else if (cont->IsSet()) { selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); } else { @@ -1825,7 +1765,8 @@ void VisitWordCompare(InstructionSelector* selector, Node* node, opcode = cont->Encode(opcode); if (cont->IsDeoptimize()) { selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, - cont->kind(), cont->reason(), cont->frame_state()); + cont->kind(), cont->reason(), cont->feedback(), + cont->frame_state()); } else if (cont->IsTrap()) { inputs[input_count++] = g.UseImmediate(cont->trap_id()); selector->Emit(opcode, output_count, outputs, input_count, inputs); @@ -1984,7 +1925,8 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user, g.Label(cont->true_block()), g.Label(cont->false_block())); } else if (cont->IsDeoptimize()) { selector->EmitDeoptimize(opcode, g.NoOutput(), value_operand, value_operand, - cont->kind(), cont->reason(), cont->frame_state()); + cont->kind(), cont->reason(), cont->feedback(), + cont->frame_state()); } else if (cont->IsSet()) { selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, value_operand); @@ -2006,14 +1948,14 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, void InstructionSelector::VisitDeoptimizeIf(Node* node) { DeoptimizeParameters p = DeoptimizeParametersOf(node->op()); FlagsContinuation cont = FlagsContinuation::ForDeoptimize( - kNotEqual, p.kind(), p.reason(), node->InputAt(1)); + kNotEqual, p.kind(), p.reason(), p.feedback(), node->InputAt(1)); VisitWordCompareZero(this, node, node->InputAt(0), &cont); } void InstructionSelector::VisitDeoptimizeUnless(Node* node) { DeoptimizeParameters p = DeoptimizeParametersOf(node->op()); FlagsContinuation cont = FlagsContinuation::ForDeoptimize( - kEqual, p.kind(), p.reason(), node->InputAt(1)); + kEqual, p.kind(), p.reason(), p.feedback(), node->InputAt(1)); VisitWordCompareZero(this, node, node->InputAt(0), &cont); } @@ -2276,15 +2218,14 @@ void InstructionSelector::VisitAtomicExchange(Node* node) { AddressingMode addressing_mode = kMode_Offset_RR; InstructionOperand inputs[3]; size_t input_count = 0; - inputs[input_count++] = g.UseUniqueRegister(base); + inputs[input_count++] = g.UseRegister(base); inputs[input_count++] = g.UseRegister(index); inputs[input_count++] = g.UseUniqueRegister(value); InstructionOperand outputs[1]; outputs[0] = g.DefineAsRegister(node); - InstructionOperand temp[1]; - temp[0] = g.TempRegister(); + InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; InstructionCode code = opcode | AddressingModeField::encode(addressing_mode); - Emit(code, 1, outputs, input_count, inputs, 1, temp); + Emit(code, 1, outputs, input_count, inputs, arraysize(temps), temps); } void InstructionSelector::VisitAtomicCompareExchange(Node* node) { @@ -2313,16 +2254,16 @@ void InstructionSelector::VisitAtomicCompareExchange(Node* node) { AddressingMode addressing_mode = kMode_Offset_RR; InstructionOperand inputs[4]; size_t input_count = 0; - inputs[input_count++] = g.UseUniqueRegister(base); + inputs[input_count++] = g.UseRegister(base); inputs[input_count++] = g.UseRegister(index); inputs[input_count++] = g.UseUniqueRegister(old_value); inputs[input_count++] = g.UseUniqueRegister(new_value); InstructionOperand outputs[1]; outputs[0] = g.DefineAsRegister(node); - InstructionOperand temp[1]; - temp[0] = g.TempRegister(); + InstructionOperand temps[] = {g.TempRegister(), g.TempRegister(), + g.TempRegister()}; InstructionCode code = opcode | AddressingModeField::encode(addressing_mode); - Emit(code, 1, outputs, input_count, inputs, 1, temp); + Emit(code, 1, outputs, input_count, inputs, arraysize(temps), temps); } void InstructionSelector::VisitAtomicBinaryOperation( @@ -2352,17 +2293,15 @@ void InstructionSelector::VisitAtomicBinaryOperation( AddressingMode addressing_mode = kMode_Offset_RR; InstructionOperand inputs[3]; size_t input_count = 0; - inputs[input_count++] = g.UseUniqueRegister(base); + inputs[input_count++] = g.UseRegister(base); inputs[input_count++] = g.UseRegister(index); inputs[input_count++] = g.UseUniqueRegister(value); InstructionOperand outputs[1]; outputs[0] = g.DefineAsRegister(node); - InstructionOperand temps[2]; - size_t temp_count = 0; - temps[temp_count++] = g.TempRegister(); - temps[temp_count++] = g.TempRegister(); + InstructionOperand temps[] = {g.TempRegister(), g.TempRegister(), + g.TempRegister()}; InstructionCode code = opcode | AddressingModeField::encode(addressing_mode); - Emit(code, 1, outputs, input_count, inputs, temp_count, temps); + Emit(code, 1, outputs, input_count, inputs, arraysize(temps), temps); } #define VISIT_ATOMIC_BINOP(op) \ |