| Index: src/arm/lithium-codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/lithium-codegen-arm.cc (revision 9984)
|
| +++ src/arm/lithium-codegen-arm.cc (working copy)
|
| @@ -40,37 +40,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 generated code there.
|
| - int call_end = codegen_->masm()->pc_offset() + call_size;
|
| - int prev_jump_end =
|
| - codegen_->LastSafepointEnd() + Deoptimizer::patch_size();
|
| - if (call_end < prev_jump_end) {
|
| - int padding_size = prev_jump_end - call_end;
|
| - ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
|
| - while (padding_size > 0) {
|
| - codegen_->masm()->nop();
|
| - padding_size -= Assembler::kInstrSize;
|
| - }
|
| - }
|
| - }
|
| + 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_;
|
| };
|
|
|
|
|
| @@ -103,7 +88,6 @@
|
| code->set_stack_slots(GetStackSlotCount());
|
| code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
|
| PopulateDeoptimizationData(code);
|
| - Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
|
| }
|
|
|
|
|
| @@ -200,7 +184,7 @@
|
| } else {
|
| __ CallRuntime(Runtime::kNewFunctionContext, 1);
|
| }
|
| - RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
|
| + RecordSafepoint(Safepoint::kNoLazyDeopt);
|
| // Context is returned in both r0 and cp. It replaces the context
|
| // passed to us. It's saved in the stack and kept live in cp.
|
| __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| @@ -249,19 +233,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) {
|
| @@ -274,13 +250,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();
|
| - }
|
| }
|
|
|
| // Force constant pool emission at the end of the deferred code to make
|
| @@ -566,7 +535,7 @@
|
| LPointerMap* pointers = instr->pointer_map();
|
| RecordPosition(pointers->position());
|
| __ Call(code, mode);
|
| - RegisterLazyDeoptimization(instr, safepoint_mode);
|
| + RecordSafepointWithLazyDeopt(instr, safepoint_mode);
|
|
|
| // Signal that we don't inline smi code before these stubs in the
|
| // optimizing code generator.
|
| @@ -586,7 +555,7 @@
|
| RecordPosition(pointers->position());
|
|
|
| __ CallRuntime(function, num_arguments);
|
| - RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT);
|
| + RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
|
| }
|
|
|
|
|
| @@ -595,37 +564,12 @@
|
| LInstruction* instr) {
|
| __ 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
|
| @@ -647,14 +591,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);
|
| @@ -716,6 +663,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);
|
| }
|
| @@ -747,16 +695,28 @@
|
| }
|
|
|
|
|
| +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(expected_safepoint_kind_ == 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()) {
|
| @@ -773,31 +733,31 @@
|
|
|
|
|
| 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);
|
| }
|
|
|
|
|
| void LCodeGen::RecordSafepointWithRegistersAndDoubles(
|
| LPointerMap* pointers,
|
| int arguments,
|
| - int deoptimization_index) {
|
| - RecordSafepoint(pointers, Safepoint::kWithRegistersAndDoubles, arguments,
|
| - deoptimization_index);
|
| + Safepoint::DeoptMode deopt_mode) {
|
| + RecordSafepoint(
|
| + pointers, Safepoint::kWithRegistersAndDoubles, arguments, deopt_mode);
|
| }
|
|
|
|
|
| @@ -832,12 +792,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);
|
| - }
|
| }
|
|
|
|
|
| @@ -1145,7 +1099,7 @@
|
| __ CallStub(&stub);
|
| RecordSafepointWithRegistersAndDoubles(instr->pointer_map(),
|
| 0,
|
| - Safepoint::kNoDeoptimizationIndex);
|
| + Safepoint::kNoLazyDeopt);
|
| // Overwrite the stored value of r0 with the result of the stub.
|
| __ StoreToSafepointRegistersAndDoublesSlot(r0, r0);
|
| }
|
| @@ -2062,7 +2016,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_; }
|
| @@ -2129,8 +2083,8 @@
|
| }
|
|
|
|
|
| -void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
| - Label* map_check) {
|
| +void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
| + Label* map_check) {
|
| Register result = ToRegister(instr->result());
|
| ASSERT(result.is(r0));
|
|
|
| @@ -2162,6 +2116,9 @@
|
| 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 result register slot and
|
| // restore all registers.
|
| __ StoreToSafepointRegisterSlot(result, result);
|
| @@ -2778,12 +2735,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);
|
| // The number of arguments is stored in receiver which is r0, as expected
|
| // by InvokeFunction.
|
| v8::internal::ParameterCount actual(receiver);
|
| @@ -2865,7 +2819,7 @@
|
| __ Call(ip);
|
|
|
| // Setup deoptimization.
|
| - RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT);
|
| + RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
|
|
|
| // Restore context.
|
| __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| @@ -3230,10 +3184,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(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
|
| __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| @@ -4560,9 +4512,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;
|
| + ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
|
| + while (padding_size > 0) {
|
| + __ nop();
|
| + padding_size -= Assembler::kInstrSize;
|
| + }
|
| + }
|
| + 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());
|
| }
|
|
|
|
|
| @@ -4579,12 +4551,9 @@
|
| __ Push(object, key, strict);
|
| 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);
|
| __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
|
| }
|
|
|
| @@ -4595,27 +4564,20 @@
|
| __ Push(key, obj);
|
| 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);
|
| __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
|
| }
|
|
|
|
|
| void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
|
| - {
|
| - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
|
| - __ 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, Safepoint::kWithRegisters);
|
| + __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
|
| + RecordSafepointWithLazyDeopt(
|
| + instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
|
| + ASSERT(instr->HasEnvironment());
|
| + LEnvironment* env = instr->environment();
|
| + safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
|
| }
|
|
|
|
|
| @@ -4630,6 +4592,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;
|
| @@ -4638,7 +4604,10 @@
|
| __ b(hs, &done);
|
| 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.
|
| @@ -4647,8 +4616,13 @@
|
| __ LoadRoot(ip, Heap::kStackLimitRootIndex);
|
| __ cmp(sp, Operand(ip));
|
| __ b(lo, 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.
|
| }
|
| }
|
|
|
| @@ -4664,7 +4638,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();
|
| }
|
|
|