| Index: src/ia32/lithium-codegen-ia32.cc
|
| ===================================================================
|
| --- src/ia32/lithium-codegen-ia32.cc (revision 9984)
|
| +++ src/ia32/lithium-codegen-ia32.cc (working copy)
|
| @@ -44,22 +44,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 {}
|
|
|
| virtual void AfterCall() const {
|
| - codegen_->RecordSafepoint(pointers_, deoptimization_index_);
|
| + codegen_->RecordSafepoint(pointers_, deopt_mode_);
|
| }
|
|
|
| private:
|
| LCodeGen* codegen_;
|
| LPointerMap* pointers_;
|
| - int deoptimization_index_;
|
| + Safepoint::DeoptMode deopt_mode_;
|
| };
|
|
|
|
|
| @@ -221,7 +221,7 @@
|
| } else {
|
| __ CallRuntime(Runtime::kNewFunctionContext, 1);
|
| }
|
| - RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
|
| + RecordSafepoint(Safepoint::kNoLazyDeopt);
|
| // Context is returned in both eax and esi. It replaces the context
|
| // passed to us. It's saved in the stack and kept live in esi.
|
| __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
|
| @@ -276,19 +276,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::GenerateDeferredCode() {
|
| ASSERT(is_generating());
|
| if (deferred_.length() > 0) {
|
| @@ -301,13 +293,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()) {
|
| - __ nop();
|
| - }
|
| }
|
|
|
| // Deferred code is the last part of the instruction sequence. Mark
|
| @@ -486,11 +471,9 @@
|
| ASSERT(instr != NULL);
|
| LPointerMap* pointers = instr->pointer_map();
|
| RecordPosition(pointers->position());
|
| -
|
| __ call(code, mode);
|
| + RecordSafepointWithLazyDeopt(instr, safepoint_mode);
|
|
|
| - RegisterLazyDeoptimization(instr, safepoint_mode);
|
| -
|
| // Signal that we don't inline smi code before these stubs in the
|
| // optimizing code generator.
|
| if (code->kind() == Code::BINARY_OP_IC ||
|
| @@ -517,7 +500,7 @@
|
|
|
| __ CallRuntime(fun, argc);
|
|
|
| - RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT);
|
| + RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
|
| }
|
|
|
|
|
| @@ -541,37 +524,12 @@
|
|
|
| __ CallRuntimeSaveDoubles(id);
|
| RecordSafepointWithRegisters(
|
| - instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex);
|
| + instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
|
| }
|
|
|
|
|
| -void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr,
|
| - SafepointMode safepoint_mode) {
|
| - // 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) {
|
| - RecordSafepoint(instr->pointer_map(),
|
| - deoptimization_environment->deoptimization_index());
|
| - } else {
|
| - ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
|
| - RecordSafepointWithRegisters(
|
| - instr->pointer_map(),
|
| - 0,
|
| - 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
|
| @@ -593,14 +551,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);
|
| @@ -680,6 +641,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);
|
| }
|
| @@ -711,15 +673,27 @@
|
| }
|
|
|
|
|
| +void LCodeGen::RecordSafepointWithLazyDeopt(
|
| + LInstruction* instr, SafepointMode safepoint_mode) {
|
| + if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
|
| + RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
|
| + } else {
|
| + ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
|
| + RecordSafepointWithRegisters(
|
| + instr->pointer_map(), 0, 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);
|
| + Safepoint safepoint =
|
| + safepoints_.DefineSafepoint(masm(), kind, arguments, deopt_mode);
|
| for (int i = 0; i < operands->length(); i++) {
|
| LOperand* pointer = operands->at(i);
|
| if (pointer->IsStackSlot()) {
|
| @@ -732,22 +706,21 @@
|
|
|
|
|
| void LCodeGen::RecordSafepoint(LPointerMap* pointers,
|
| - int deoptimization_index) {
|
| - RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index);
|
| + Safepoint::DeoptMode mode) {
|
| + RecordSafepoint(pointers, Safepoint::kSimple, 0, mode);
|
| }
|
|
|
|
|
| -void LCodeGen::RecordSafepoint(int deoptimization_index) {
|
| +void LCodeGen::RecordSafepoint(Safepoint::DeoptMode mode) {
|
| LPointerMap empty_pointers(RelocInfo::kNoPosition);
|
| - RecordSafepoint(&empty_pointers, deoptimization_index);
|
| + RecordSafepoint(&empty_pointers, mode);
|
| }
|
|
|
|
|
| void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
|
| int arguments,
|
| - int deoptimization_index) {
|
| - RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments,
|
| - deoptimization_index);
|
| + Safepoint::DeoptMode mode) {
|
| + RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, mode);
|
| }
|
|
|
|
|
| @@ -782,12 +755,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);
|
| - }
|
| }
|
|
|
|
|
| @@ -1928,7 +1895,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_; }
|
| @@ -1983,8 +1950,8 @@
|
| }
|
|
|
|
|
| -void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
| - Label* map_check) {
|
| +void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
| + Label* map_check) {
|
| PushSafepointRegistersScope scope(this);
|
|
|
| InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
|
| @@ -2011,6 +1978,10 @@
|
| RelocInfo::CODE_TARGET,
|
| instr,
|
| RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
|
| + ASSERT(instr->HasDeoptimizationEnvironment());
|
| + LEnvironment* env = instr->deoptimization_environment();
|
| + safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
|
| +
|
| // Put the result value into the eax slot and restore all registers.
|
| __ StoreToSafepointRegisterSlot(eax, eax);
|
| }
|
| @@ -2616,12 +2587,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);
|
| ParameterCount actual(eax);
|
| __ InvokeFunction(function, actual, CALL_FUNCTION,
|
| safepoint_generator, CALL_AS_METHOD);
|
| @@ -2704,8 +2672,7 @@
|
| __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
|
| }
|
|
|
| - // Setup deoptimization.
|
| - RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT);
|
| + RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
|
| }
|
|
|
|
|
| @@ -3081,10 +3048,9 @@
|
| 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(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
| }
|
| @@ -3657,7 +3623,7 @@
|
| __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
|
| RecordSafepointWithRegisters(
|
| - instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
|
| + instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
|
| if (!reg.is(eax)) __ mov(reg, eax);
|
|
|
| // Done. Put the value in xmm0 into the value of the allocated heap
|
| @@ -3709,8 +3675,8 @@
|
| // not have easy access to the local context.
|
| __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
|
| - RecordSafepointWithRegisters(instr->pointer_map(), 0,
|
| - Safepoint::kNoDeoptimizationIndex);
|
| + RecordSafepointWithRegisters(
|
| + instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
|
| __ StoreToSafepointRegisterSlot(reg, eax);
|
| }
|
|
|
| @@ -4453,9 +4419,27 @@
|
| }
|
|
|
|
|
| +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) {
|
| + __ nop();
|
| + }
|
| + }
|
| + 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());
|
| }
|
|
|
|
|
| @@ -4475,32 +4459,26 @@
|
| }
|
| 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(Immediate(Smi::FromInt(strict_mode_flag())));
|
| __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
|
| }
|
|
|
|
|
| void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
|
| - {
|
| - PushSafepointRegistersScope scope(this);
|
| - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| - __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
|
| - RegisterLazyDeoptimization(
|
| - instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
|
| - }
|
| -
|
| - // The gap code includes the restoring of the safepoint registers.
|
| - int pc = masm()->pc_offset();
|
| - safepoints_.SetPcAfterGap(pc);
|
| + PushSafepointRegistersScope scope(this);
|
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| + __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
|
| + RecordSafepointWithLazyDeopt(
|
| + instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
|
| + ASSERT(instr->HasEnvironment());
|
| + LEnvironment* env = instr->environment();
|
| + safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
|
| }
|
|
|
|
|
| @@ -4515,6 +4493,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;
|
| @@ -4527,7 +4509,10 @@
|
| ASSERT(ToRegister(instr->context()).is(esi));
|
| 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.
|
| @@ -4537,8 +4522,13 @@
|
| ExternalReference::address_of_stack_limit(isolate());
|
| __ cmp(esp, Operand::StaticVariable(stack_limit));
|
| __ 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.
|
| }
|
| }
|
|
|
| @@ -4554,7 +4544,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();
|
| }
|
| @@ -4575,15 +4565,9 @@
|
| }
|
| 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);
|
| }
|
|
|
|
|