| Index: src/x64/lithium-codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/lithium-codegen-x64.cc (revision 9984)
|
| +++ src/x64/lithium-codegen-x64.cc (working copy)
|
| @@ -43,35 +43,22 @@
|
| public:
|
| SafepointGenerator(LCodeGen* codegen,
|
| LPointerMap* pointers,
|
| - int deoptimization_index)
|
| + Safepoint::DeoptMode mode)
|
| : codegen_(codegen),
|
| pointers_(pointers),
|
| - deoptimization_index_(deoptimization_index) { }
|
| + deopt_mode_(mode) { }
|
| virtual ~SafepointGenerator() { }
|
|
|
| - virtual void BeforeCall(int call_size) const {
|
| - ASSERT(call_size >= 0);
|
| - // Ensure that we have enough space after the previous safepoint position
|
| - // for the jump generated there.
|
| - int call_end = codegen_->masm()->pc_offset() + call_size;
|
| - int prev_jump_end = codegen_->LastSafepointEnd() + kMinSafepointSize;
|
| - if (call_end < prev_jump_end) {
|
| - int padding_size = prev_jump_end - call_end;
|
| - STATIC_ASSERT(kMinSafepointSize <= 9); // One multibyte nop is enough.
|
| - codegen_->masm()->nop(padding_size);
|
| - }
|
| - }
|
| + virtual void BeforeCall(int call_size) const { }
|
|
|
| virtual void AfterCall() const {
|
| - codegen_->RecordSafepoint(pointers_, deoptimization_index_);
|
| + codegen_->RecordSafepoint(pointers_, deopt_mode_);
|
| }
|
|
|
| private:
|
| - static const int kMinSafepointSize =
|
| - MacroAssembler::kShortCallInstructionLength;
|
| LCodeGen* codegen_;
|
| LPointerMap* pointers_;
|
| - int deoptimization_index_;
|
| + Safepoint::DeoptMode deopt_mode_;
|
| };
|
|
|
|
|
| @@ -100,7 +87,6 @@
|
| code->set_stack_slots(GetStackSlotCount());
|
| code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
|
| PopulateDeoptimizationData(code);
|
| - Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
|
| }
|
|
|
|
|
| @@ -206,7 +192,7 @@
|
| } else {
|
| __ CallRuntime(Runtime::kNewFunctionContext, 1);
|
| }
|
| - RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
|
| + RecordSafepoint(Safepoint::kNoLazyDeopt);
|
| // Context is returned in both rax and rsi. It replaces the context
|
| // passed to us. It's saved in the stack and kept live in rsi.
|
| __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
|
| @@ -255,19 +241,11 @@
|
| instr->CompileToNative(this);
|
| }
|
| }
|
| + EnsureSpaceForLazyDeopt();
|
| return !is_aborted();
|
| }
|
|
|
|
|
| -LInstruction* LCodeGen::GetNextInstruction() {
|
| - if (current_instruction_ < instructions_->length() - 1) {
|
| - return instructions_->at(current_instruction_ + 1);
|
| - } else {
|
| - return NULL;
|
| - }
|
| -}
|
| -
|
| -
|
| bool LCodeGen::GenerateJumpTable() {
|
| for (int i = 0; i < jump_table_.length(); i++) {
|
| __ bind(&jump_table_[i].label);
|
| @@ -289,18 +267,6 @@
|
| code->Generate();
|
| __ jmp(code->exit());
|
| }
|
| -
|
| - // Pad code to ensure that the last piece of deferred code have
|
| - // room for lazy bailout.
|
| - while ((masm()->pc_offset() - LastSafepointEnd())
|
| - < Deoptimizer::patch_size()) {
|
| - int padding = masm()->pc_offset() - LastSafepointEnd();
|
| - if (padding > 9) {
|
| - __ nop(9);
|
| - } else {
|
| - __ nop(padding);
|
| - }
|
| - }
|
| }
|
|
|
| // Deferred code is the last part of the instruction sequence. Mark
|
| @@ -312,20 +278,6 @@
|
|
|
| bool LCodeGen::GenerateSafepointTable() {
|
| ASSERT(is_done());
|
| - // Ensure that there is space at the end of the code to write a number
|
| - // of jump instructions, as well as to afford writing a call near the end
|
| - // of the code.
|
| - // The jumps are used when there isn't room in the code stream to write
|
| - // a long call instruction. Instead it writes a shorter call to a
|
| - // jump instruction in the same code object.
|
| - // The calls are used when lazy deoptimizing a function and calls to a
|
| - // deoptimization function.
|
| - int short_deopts = safepoints_.CountShortDeoptimizationIntervals(
|
| - static_cast<unsigned>(MacroAssembler::kJumpInstructionLength));
|
| - int byte_count = (short_deopts) * MacroAssembler::kJumpInstructionLength;
|
| - while (byte_count-- > 0) {
|
| - __ int3();
|
| - }
|
| safepoints_.Emit(masm(), GetStackSlotCount());
|
| return !is_aborted();
|
| }
|
| @@ -491,7 +443,7 @@
|
| LPointerMap* pointers = instr->pointer_map();
|
| RecordPosition(pointers->position());
|
| __ call(code, mode);
|
| - RegisterLazyDeoptimization(instr, safepoint_mode, argc);
|
| + RecordSafepointWithLazyDeopt(instr, safepoint_mode, argc);
|
|
|
| // Signal that we don't inline smi code before these stubs in the
|
| // optimizing code generator.
|
| @@ -518,7 +470,7 @@
|
| RecordPosition(pointers->position());
|
|
|
| __ CallRuntime(function, num_arguments);
|
| - RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0);
|
| + RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0);
|
| }
|
|
|
|
|
| @@ -528,39 +480,12 @@
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| __ CallRuntimeSaveDoubles(id);
|
| RecordSafepointWithRegisters(
|
| - instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex);
|
| + instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
|
| }
|
|
|
|
|
| -void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr,
|
| - SafepointMode safepoint_mode,
|
| - int argc) {
|
| - // Create the environment to bailout to. If the call has side effects
|
| - // execution has to continue after the call otherwise execution can continue
|
| - // from a previous bailout point repeating the call.
|
| - LEnvironment* deoptimization_environment;
|
| - if (instr->HasDeoptimizationEnvironment()) {
|
| - deoptimization_environment = instr->deoptimization_environment();
|
| - } else {
|
| - deoptimization_environment = instr->environment();
|
| - }
|
| -
|
| - RegisterEnvironmentForDeoptimization(deoptimization_environment);
|
| - if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
|
| - ASSERT(argc == 0);
|
| - RecordSafepoint(instr->pointer_map(),
|
| - deoptimization_environment->deoptimization_index());
|
| - } else {
|
| - ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS);
|
| - RecordSafepointWithRegisters(
|
| - instr->pointer_map(),
|
| - argc,
|
| - deoptimization_environment->deoptimization_index());
|
| - }
|
| -}
|
| -
|
| -
|
| -void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) {
|
| +void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
|
| + Safepoint::DeoptMode mode) {
|
| if (!environment->HasBeenRegistered()) {
|
| // Physical stack frame layout:
|
| // -x ............. -4 0 ..................................... y
|
| @@ -582,14 +507,17 @@
|
| Translation translation(&translations_, frame_count);
|
| WriteTranslation(environment, &translation);
|
| int deoptimization_index = deoptimizations_.length();
|
| - environment->Register(deoptimization_index, translation.index());
|
| + int pc_offset = masm()->pc_offset();
|
| + environment->Register(deoptimization_index,
|
| + translation.index(),
|
| + (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
|
| deoptimizations_.Add(environment);
|
| }
|
| }
|
|
|
|
|
| void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) {
|
| - RegisterEnvironmentForDeoptimization(environment);
|
| + RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
|
| ASSERT(environment->HasBeenRegistered());
|
| int id = environment->deoptimization_index();
|
| Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER);
|
| @@ -641,6 +569,7 @@
|
| data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
|
| data->SetArgumentsStackHeight(i,
|
| Smi::FromInt(env->arguments_stack_height()));
|
| + data->SetPc(i, Smi::FromInt(env->pc_offset()));
|
| }
|
| code->set_deoptimization_data(*data);
|
| }
|
| @@ -672,17 +601,29 @@
|
| }
|
|
|
|
|
| +void LCodeGen::RecordSafepointWithLazyDeopt(
|
| + LInstruction* instr, SafepointMode safepoint_mode, int argc) {
|
| + if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
|
| + RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
|
| + } else {
|
| + ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS);
|
| + RecordSafepointWithRegisters(
|
| + instr->pointer_map(), argc, Safepoint::kLazyDeopt);
|
| + }
|
| +}
|
| +
|
| +
|
| void LCodeGen::RecordSafepoint(
|
| LPointerMap* pointers,
|
| Safepoint::Kind kind,
|
| int arguments,
|
| - int deoptimization_index) {
|
| + Safepoint::DeoptMode deopt_mode) {
|
| ASSERT(kind == expected_safepoint_kind_);
|
|
|
| const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
|
|
|
| Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
|
| - kind, arguments, deoptimization_index);
|
| + kind, arguments, deopt_mode);
|
| for (int i = 0; i < operands->length(); i++) {
|
| LOperand* pointer = operands->at(i);
|
| if (pointer->IsStackSlot()) {
|
| @@ -699,22 +640,21 @@
|
|
|
|
|
| void LCodeGen::RecordSafepoint(LPointerMap* pointers,
|
| - int deoptimization_index) {
|
| - RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index);
|
| + Safepoint::DeoptMode deopt_mode) {
|
| + RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode);
|
| }
|
|
|
|
|
| -void LCodeGen::RecordSafepoint(int deoptimization_index) {
|
| +void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
|
| LPointerMap empty_pointers(RelocInfo::kNoPosition);
|
| - RecordSafepoint(&empty_pointers, deoptimization_index);
|
| + RecordSafepoint(&empty_pointers, deopt_mode);
|
| }
|
|
|
|
|
| void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
|
| int arguments,
|
| - int deoptimization_index) {
|
| - RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments,
|
| - deoptimization_index);
|
| + Safepoint::DeoptMode deopt_mode) {
|
| + RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
|
| }
|
|
|
|
|
| @@ -749,12 +689,6 @@
|
| LParallelMove* move = gap->GetParallelMove(inner_pos);
|
| if (move != NULL) DoParallelMove(move);
|
| }
|
| -
|
| - LInstruction* next = GetNextInstruction();
|
| - if (next != NULL && next->IsLazyBailout()) {
|
| - int pc = masm()->pc_offset();
|
| - safepoints_.SetPcAfterGap(pc);
|
| - }
|
| }
|
|
|
|
|
| @@ -1889,7 +1823,7 @@
|
| LInstanceOfKnownGlobal* instr)
|
| : LDeferredCode(codegen), instr_(instr) { }
|
| virtual void Generate() {
|
| - codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_);
|
| + codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
|
| }
|
| virtual LInstruction* instr() { return instr_; }
|
| Label* map_check() { return &map_check_; }
|
| @@ -1947,8 +1881,8 @@
|
| }
|
|
|
|
|
| -void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
| - Label* map_check) {
|
| +void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
| + Label* map_check) {
|
| {
|
| PushSafepointRegistersScope scope(this);
|
| InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>(
|
| @@ -1974,6 +1908,9 @@
|
| RECORD_SAFEPOINT_WITH_REGISTERS,
|
| 2);
|
| ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check));
|
| + ASSERT(instr->HasDeoptimizationEnvironment());
|
| + LEnvironment* env = instr->deoptimization_environment();
|
| + safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
|
| // Move result to a register that survives the end of the
|
| // PushSafepointRegisterScope.
|
| __ movq(kScratchRegister, rax);
|
| @@ -2569,12 +2506,9 @@
|
| __ bind(&invoke);
|
| ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
|
| LPointerMap* pointers = instr->pointer_map();
|
| - LEnvironment* env = instr->deoptimization_environment();
|
| RecordPosition(pointers->position());
|
| - RegisterEnvironmentForDeoptimization(env);
|
| - SafepointGenerator safepoint_generator(this,
|
| - pointers,
|
| - env->deoptimization_index());
|
| + SafepointGenerator safepoint_generator(
|
| + this, pointers, Safepoint::kLazyDeopt);
|
| v8::internal::ParameterCount actual(rax);
|
| __ InvokeFunction(function, actual, CALL_FUNCTION,
|
| safepoint_generator, CALL_AS_METHOD);
|
| @@ -2652,7 +2586,7 @@
|
| }
|
|
|
| // Setup deoptimization.
|
| - RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT, 0);
|
| + RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0);
|
|
|
| // Restore context.
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| @@ -3000,10 +2934,8 @@
|
| ASSERT(instr->HasPointerMap());
|
| ASSERT(instr->HasDeoptimizationEnvironment());
|
| LPointerMap* pointers = instr->pointer_map();
|
| - LEnvironment* env = instr->deoptimization_environment();
|
| RecordPosition(pointers->position());
|
| - RegisterEnvironmentForDeoptimization(env);
|
| - SafepointGenerator generator(this, pointers, env->deoptimization_index());
|
| + SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
|
| ParameterCount count(instr->arity());
|
| __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
| __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| @@ -4184,9 +4116,29 @@
|
| }
|
|
|
|
|
| +void LCodeGen::EnsureSpaceForLazyDeopt() {
|
| + // Ensure that we have enough space after the previous lazy-bailout
|
| + // instruction for patching the code here.
|
| + int current_pc = masm()->pc_offset();
|
| + int patch_size = Deoptimizer::patch_size();
|
| + if (current_pc < last_lazy_deopt_pc_ + patch_size) {
|
| + int padding_size = last_lazy_deopt_pc_ + patch_size - current_pc;
|
| + while (padding_size > 0) {
|
| + int nop_size = padding_size > 9 ? 9 : padding_size;
|
| + __ nop(nop_size);
|
| + padding_size -= nop_size;
|
| + }
|
| + }
|
| + last_lazy_deopt_pc_ = current_pc;
|
| +}
|
| +
|
| +
|
| void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
|
| - // No code for lazy bailout instruction. Used to capture environment after a
|
| - // call for populating the safepoint data with deoptimization data.
|
| + EnsureSpaceForLazyDeopt();
|
| + ASSERT(instr->HasEnvironment());
|
| + LEnvironment* env = instr->environment();
|
| + RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
|
| + safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
|
| }
|
|
|
|
|
| @@ -4202,15 +4154,12 @@
|
| EmitPushTaggedOperand(key);
|
| ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
|
| LPointerMap* pointers = instr->pointer_map();
|
| - LEnvironment* env = instr->deoptimization_environment();
|
| RecordPosition(pointers->position());
|
| - RegisterEnvironmentForDeoptimization(env);
|
| // Create safepoint generator that will also ensure enough space in the
|
| // reloc info for patching in deoptimization (since this is invoking a
|
| // builtin)
|
| - SafepointGenerator safepoint_generator(this,
|
| - pointers,
|
| - env->deoptimization_index());
|
| + SafepointGenerator safepoint_generator(
|
| + this, pointers, Safepoint::kLazyDeopt);
|
| __ Push(Smi::FromInt(strict_mode_flag()));
|
| __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
|
| }
|
| @@ -4223,30 +4172,21 @@
|
| EmitPushTaggedOperand(obj);
|
| ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
|
| LPointerMap* pointers = instr->pointer_map();
|
| - LEnvironment* env = instr->deoptimization_environment();
|
| RecordPosition(pointers->position());
|
| - RegisterEnvironmentForDeoptimization(env);
|
| - // Create safepoint generator that will also ensure enough space in the
|
| - // reloc info for patching in deoptimization (since this is invoking a
|
| - // builtin)
|
| - SafepointGenerator safepoint_generator(this,
|
| - pointers,
|
| - env->deoptimization_index());
|
| + SafepointGenerator safepoint_generator(
|
| + this, pointers, Safepoint::kLazyDeopt);
|
| __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
|
| }
|
|
|
|
|
| void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
|
| - {
|
| - PushSafepointRegistersScope scope(this);
|
| - __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| - __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
|
| - RegisterLazyDeoptimization(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0);
|
| - }
|
| -
|
| - // The gap code includes the restoring of the safepoint registers.
|
| - int pc = masm()->pc_offset();
|
| - safepoints_.SetPcAfterGap(pc);
|
| + PushSafepointRegistersScope scope(this);
|
| + __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
|
| + RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0);
|
| + ASSERT(instr->HasEnvironment());
|
| + LEnvironment* env = instr->environment();
|
| + safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
|
| }
|
|
|
|
|
| @@ -4261,6 +4201,10 @@
|
| LStackCheck* instr_;
|
| };
|
|
|
| + ASSERT(instr->HasEnvironment());
|
| + LEnvironment* env = instr->environment();
|
| + // There is no LLazyBailout instruction for stack-checks. We have to
|
| + // prepare for lazy deoptimization explicitly here.
|
| if (instr->hydrogen()->is_function_entry()) {
|
| // Perform stack overflow check.
|
| Label done;
|
| @@ -4268,7 +4212,10 @@
|
| __ j(above_equal, &done, Label::kNear);
|
| StackCheckStub stub;
|
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| + EnsureSpaceForLazyDeopt();
|
| __ bind(&done);
|
| + RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
|
| + safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
|
| } else {
|
| ASSERT(instr->hydrogen()->is_backwards_branch());
|
| // Perform stack overflow check if this goto needs it before jumping.
|
| @@ -4276,8 +4223,13 @@
|
| new DeferredStackCheck(this, instr);
|
| __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
|
| __ j(below, deferred_stack_check->entry());
|
| + EnsureSpaceForLazyDeopt();
|
| __ bind(instr->done_label());
|
| deferred_stack_check->SetExit(instr->done_label());
|
| + RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
|
| + // Don't record a deoptimization index for the safepoint here.
|
| + // This will be done explicitly when emitting call and the safepoint in
|
| + // the deferred code.
|
| }
|
| }
|
|
|
| @@ -4293,7 +4245,7 @@
|
| // If the environment were already registered, we would have no way of
|
| // backpatching it with the spill slot operands.
|
| ASSERT(!environment->HasBeenRegistered());
|
| - RegisterEnvironmentForDeoptimization(environment);
|
| + RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
|
| ASSERT(osr_pc_offset_ == -1);
|
| osr_pc_offset_ = masm()->pc_offset();
|
| }
|
|
|