OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 if (deopt_jump_table_.length() > 0) { | 353 if (deopt_jump_table_.length() > 0) { |
354 Comment(";;; -------------------- Jump table --------------------"); | 354 Comment(";;; -------------------- Jump table --------------------"); |
355 } | 355 } |
356 Label table_start; | 356 Label table_start; |
357 __ bind(&table_start); | 357 __ bind(&table_start); |
358 Label needs_frame_not_call; | 358 Label needs_frame_not_call; |
359 Label needs_frame_is_call; | 359 Label needs_frame_is_call; |
360 for (int i = 0; i < deopt_jump_table_.length(); i++) { | 360 for (int i = 0; i < deopt_jump_table_.length(); i++) { |
361 __ bind(&deopt_jump_table_[i].label); | 361 __ bind(&deopt_jump_table_[i].label); |
362 Address entry = deopt_jump_table_[i].address; | 362 Address entry = deopt_jump_table_[i].address; |
363 bool is_lazy_deopt = deopt_jump_table_[i].is_lazy_deopt; | 363 Deoptimizer::BailoutType type = deopt_jump_table_[i].bailout_type; |
364 Deoptimizer::BailoutType type = | |
365 is_lazy_deopt ? Deoptimizer::LAZY : Deoptimizer::EAGER; | |
366 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | 364 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); |
367 if (id == Deoptimizer::kNotDeoptimizationEntry) { | 365 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
368 Comment(";;; jump table entry %d.", i); | 366 Comment(";;; jump table entry %d.", i); |
369 } else { | 367 } else { |
370 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | 368 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
371 } | 369 } |
372 if (deopt_jump_table_[i].needs_frame) { | 370 if (deopt_jump_table_[i].needs_frame) { |
373 __ mov(ip, Operand(ExternalReference::ForDeoptEntry(entry))); | 371 __ mov(ip, Operand(ExternalReference::ForDeoptEntry(entry))); |
374 if (is_lazy_deopt) { | 372 if (type == Deoptimizer::LAZY) { |
375 if (needs_frame_is_call.is_bound()) { | 373 if (needs_frame_is_call.is_bound()) { |
376 __ b(&needs_frame_is_call); | 374 __ b(&needs_frame_is_call); |
377 } else { | 375 } else { |
378 __ bind(&needs_frame_is_call); | 376 __ bind(&needs_frame_is_call); |
379 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 377 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
380 // This variant of deopt can only be used with stubs. Since we don't | 378 // This variant of deopt can only be used with stubs. Since we don't |
381 // have a function pointer to install in the stack frame that we're | 379 // have a function pointer to install in the stack frame that we're |
382 // building, install a special marker there instead. | 380 // building, install a special marker there instead. |
383 ASSERT(info()->IsStub()); | 381 ASSERT(info()->IsStub()); |
384 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | 382 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); |
(...skipping 12 matching lines...) Expand all Loading... |
397 // have a function pointer to install in the stack frame that we're | 395 // have a function pointer to install in the stack frame that we're |
398 // building, install a special marker there instead. | 396 // building, install a special marker there instead. |
399 ASSERT(info()->IsStub()); | 397 ASSERT(info()->IsStub()); |
400 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | 398 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); |
401 __ push(scratch0()); | 399 __ push(scratch0()); |
402 __ add(fp, sp, Operand(2 * kPointerSize)); | 400 __ add(fp, sp, Operand(2 * kPointerSize)); |
403 __ mov(pc, ip); | 401 __ mov(pc, ip); |
404 } | 402 } |
405 } | 403 } |
406 } else { | 404 } else { |
407 if (is_lazy_deopt) { | 405 if (type == Deoptimizer::LAZY) { |
408 __ mov(lr, Operand(pc), LeaveCC, al); | 406 __ mov(lr, Operand(pc), LeaveCC, al); |
409 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); | 407 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); |
410 } else { | 408 } else { |
411 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); | 409 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); |
412 } | 410 } |
413 } | 411 } |
414 masm()->CheckConstPool(false, false); | 412 masm()->CheckConstPool(false, false); |
415 } | 413 } |
416 | 414 |
417 // Force constant pool emission at the end of the deopt jump table to make | 415 // Force constant pool emission at the end of the deopt jump table to make |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
826 int deoptimization_index = deoptimizations_.length(); | 824 int deoptimization_index = deoptimizations_.length(); |
827 int pc_offset = masm()->pc_offset(); | 825 int pc_offset = masm()->pc_offset(); |
828 environment->Register(deoptimization_index, | 826 environment->Register(deoptimization_index, |
829 translation.index(), | 827 translation.index(), |
830 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 828 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
831 deoptimizations_.Add(environment, zone()); | 829 deoptimizations_.Add(environment, zone()); |
832 } | 830 } |
833 } | 831 } |
834 | 832 |
835 | 833 |
836 void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) { | 834 void LCodeGen::DeoptimizeIf(Condition cc, |
| 835 LEnvironment* environment, |
| 836 Deoptimizer::BailoutType bailout_type) { |
837 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 837 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
838 ASSERT(environment->HasBeenRegistered()); | 838 ASSERT(environment->HasBeenRegistered()); |
839 int id = environment->deoptimization_index(); | 839 int id = environment->deoptimization_index(); |
840 ASSERT(info()->IsOptimizing() || info()->IsStub()); | 840 ASSERT(info()->IsOptimizing() || info()->IsStub()); |
841 Deoptimizer::BailoutType bailout_type = info()->IsStub() | |
842 ? Deoptimizer::LAZY | |
843 : Deoptimizer::EAGER; | |
844 Address entry = | 841 Address entry = |
845 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 842 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
846 if (entry == NULL) { | 843 if (entry == NULL) { |
847 Abort("bailout was not prepared"); | 844 Abort("bailout was not prepared"); |
848 return; | 845 return; |
849 } | 846 } |
850 | 847 |
851 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on ARM. | 848 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on ARM. |
852 if (FLAG_deopt_every_n_times == 1 && | 849 if (FLAG_deopt_every_n_times == 1 && |
853 !info()->IsStub() && | 850 !info()->IsStub() && |
(...skipping 12 matching lines...) Expand all Loading... |
866 if (needs_lazy_deopt) { | 863 if (needs_lazy_deopt) { |
867 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 864 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
868 } else { | 865 } else { |
869 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); | 866 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); |
870 } | 867 } |
871 } else { | 868 } else { |
872 // We often have several deopts to the same entry, reuse the last | 869 // We often have several deopts to the same entry, reuse the last |
873 // jump entry if this is the case. | 870 // jump entry if this is the case. |
874 if (deopt_jump_table_.is_empty() || | 871 if (deopt_jump_table_.is_empty() || |
875 (deopt_jump_table_.last().address != entry) || | 872 (deopt_jump_table_.last().address != entry) || |
876 (deopt_jump_table_.last().is_lazy_deopt != needs_lazy_deopt) || | 873 (deopt_jump_table_.last().bailout_type != bailout_type) || |
877 (deopt_jump_table_.last().needs_frame != !frame_is_built_)) { | 874 (deopt_jump_table_.last().needs_frame != !frame_is_built_)) { |
878 JumpTableEntry table_entry(entry, !frame_is_built_, needs_lazy_deopt); | 875 Deoptimizer::JumpTableEntry table_entry(entry, |
| 876 bailout_type, |
| 877 !frame_is_built_); |
879 deopt_jump_table_.Add(table_entry, zone()); | 878 deopt_jump_table_.Add(table_entry, zone()); |
880 } | 879 } |
881 __ b(cc, &deopt_jump_table_.last().label); | 880 __ b(cc, &deopt_jump_table_.last().label); |
882 } | 881 } |
883 } | 882 } |
884 | 883 |
885 | 884 |
| 885 void LCodeGen::DeoptimizeIf(Condition cc, |
| 886 LEnvironment* environment) { |
| 887 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
| 888 ? Deoptimizer::LAZY |
| 889 : Deoptimizer::EAGER; |
| 890 DeoptimizeIf(cc, environment, bailout_type); |
| 891 } |
| 892 |
| 893 |
| 894 void LCodeGen::SoftDeoptimize(LEnvironment* environment) { |
| 895 ASSERT(!info()->IsStub()); |
| 896 DeoptimizeIf(al, environment, Deoptimizer::SOFT); |
| 897 } |
| 898 |
| 899 |
886 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { | 900 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { |
887 ZoneList<Handle<Map> > maps(1, zone()); | 901 ZoneList<Handle<Map> > maps(1, zone()); |
888 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 902 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
889 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | 903 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { |
890 RelocInfo::Mode mode = it.rinfo()->rmode(); | 904 RelocInfo::Mode mode = it.rinfo()->rmode(); |
891 if (mode == RelocInfo::EMBEDDED_OBJECT && | 905 if (mode == RelocInfo::EMBEDDED_OBJECT && |
892 it.rinfo()->target_object()->IsMap()) { | 906 it.rinfo()->target_object()->IsMap()) { |
893 Handle<Map> map(Map::cast(it.rinfo()->target_object())); | 907 Handle<Map> map(Map::cast(it.rinfo()->target_object())); |
894 if (map->CanTransition()) { | 908 if (map->CanTransition()) { |
895 maps.Add(map, zone()); | 909 maps.Add(map, zone()); |
(...skipping 4819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5715 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 5729 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
5716 EnsureSpaceForLazyDeopt(); | 5730 EnsureSpaceForLazyDeopt(); |
5717 ASSERT(instr->HasEnvironment()); | 5731 ASSERT(instr->HasEnvironment()); |
5718 LEnvironment* env = instr->environment(); | 5732 LEnvironment* env = instr->environment(); |
5719 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5733 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
5720 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5734 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
5721 } | 5735 } |
5722 | 5736 |
5723 | 5737 |
5724 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5738 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
5725 DeoptimizeIf(al, instr->environment()); | 5739 if (instr->hydrogen_value()->IsSoftDeoptimize()) { |
| 5740 SoftDeoptimize(instr->environment()); |
| 5741 } else { |
| 5742 DeoptimizeIf(al, instr->environment()); |
| 5743 } |
5726 } | 5744 } |
5727 | 5745 |
5728 | 5746 |
5729 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5747 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
5730 // Nothing to see here, move on! | 5748 // Nothing to see here, move on! |
5731 } | 5749 } |
5732 | 5750 |
5733 | 5751 |
5734 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { | 5752 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { |
5735 Register object = ToRegister(instr->object()); | 5753 Register object = ToRegister(instr->object()); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5923 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); | 5941 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); |
5924 __ ldr(result, FieldMemOperand(scratch, | 5942 __ ldr(result, FieldMemOperand(scratch, |
5925 FixedArray::kHeaderSize - kPointerSize)); | 5943 FixedArray::kHeaderSize - kPointerSize)); |
5926 __ bind(&done); | 5944 __ bind(&done); |
5927 } | 5945 } |
5928 | 5946 |
5929 | 5947 |
5930 #undef __ | 5948 #undef __ |
5931 | 5949 |
5932 } } // namespace v8::internal | 5950 } } // namespace v8::internal |
OLD | NEW |