Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/arm64/lithium-codegen-arm64.h" | 7 #include "src/arm64/lithium-codegen-arm64.h" |
| 8 #include "src/arm64/lithium-gap-resolver-arm64.h" | 8 #include "src/arm64/lithium-gap-resolver-arm64.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/stub-cache.h" | 10 #include "src/stub-cache.h" |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 380 LInstruction* instr) { | 380 LInstruction* instr) { |
| 381 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); | 381 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); |
| 382 } | 382 } |
| 383 | 383 |
| 384 | 384 |
| 385 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 385 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 386 RelocInfo::Mode mode, | 386 RelocInfo::Mode mode, |
| 387 LInstruction* instr, | 387 LInstruction* instr, |
| 388 SafepointMode safepoint_mode) { | 388 SafepointMode safepoint_mode) { |
| 389 ASSERT(instr != NULL); | 389 ASSERT(instr != NULL); |
| 390 ASSERT(instr->IsMarkedAsCall()); | |
| 390 | 391 |
| 391 Assembler::BlockPoolsScope scope(masm_); | 392 Assembler::BlockPoolsScope scope(masm_); |
| 392 __ Call(code, mode); | 393 __ Call(code, mode); |
| 393 RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 394 RecordSafepointWithLazyDeopt(instr, safepoint_mode); |
| 394 | 395 |
| 395 if ((code->kind() == Code::BINARY_OP_IC) || | 396 if ((code->kind() == Code::BINARY_OP_IC) || |
| 396 (code->kind() == Code::COMPARE_IC)) { | 397 (code->kind() == Code::COMPARE_IC)) { |
| 397 // Signal that we don't inline smi code before these stubs in the | 398 // Signal that we don't inline smi code before these stubs in the |
| 398 // optimizing code generator. | 399 // optimizing code generator. |
| 399 InlineSmiCheckInfo::EmitNotInlined(masm()); | 400 InlineSmiCheckInfo::EmitNotInlined(masm()); |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 832 | 833 |
| 833 | 834 |
| 834 bool LCodeGen::GenerateDeoptJumpTable() { | 835 bool LCodeGen::GenerateDeoptJumpTable() { |
| 835 Label needs_frame, restore_caller_doubles, call_deopt_entry; | 836 Label needs_frame, restore_caller_doubles, call_deopt_entry; |
| 836 | 837 |
| 837 if (deopt_jump_table_.length() > 0) { | 838 if (deopt_jump_table_.length() > 0) { |
| 838 Comment(";;; -------------------- Jump table --------------------"); | 839 Comment(";;; -------------------- Jump table --------------------"); |
| 839 Address base = deopt_jump_table_[0]->address; | 840 Address base = deopt_jump_table_[0]->address; |
| 840 | 841 |
| 841 UseScratchRegisterScope temps(masm()); | 842 UseScratchRegisterScope temps(masm()); |
| 842 Register entry_offset = temps.AcquireX(); | 843 // This is reused as the caller address later, and the second-level deopt |
| 844 // table expects this in ip1. | |
| 845 Register entry_offset = temps.Acquire(ip1); | |
|
ulan
2014/06/23 11:17:11
Nit: maybe introduce a descriptive alias for ip1 t
jbramley
2014/06/23 17:22:05
Done.
| |
| 843 | 846 |
| 844 int length = deopt_jump_table_.length(); | 847 int length = deopt_jump_table_.length(); |
| 845 for (int i = 0; i < length; i++) { | 848 for (int i = 0; i < length; i++) { |
| 846 __ Bind(&deopt_jump_table_[i]->label); | 849 __ Bind(&deopt_jump_table_[i]->label); |
| 847 | 850 |
| 848 Deoptimizer::BailoutType type = deopt_jump_table_[i]->bailout_type; | 851 Deoptimizer::BailoutType type = deopt_jump_table_[i]->bailout_type; |
| 849 Address entry = deopt_jump_table_[i]->address; | 852 Address entry = deopt_jump_table_[i]->address; |
| 850 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | 853 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); |
| 851 if (id == Deoptimizer::kNotDeoptimizationEntry) { | 854 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
| 852 Comment(";;; jump table entry %d.", i); | 855 Comment(";;; jump table entry %d.", i); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 900 | 903 |
| 901 masm()->CheckConstPool(false, last_entry); | 904 masm()->CheckConstPool(false, last_entry); |
| 902 } | 905 } |
| 903 | 906 |
| 904 // Generate common code for calling the second-level deopt table. | 907 // Generate common code for calling the second-level deopt table. |
| 905 Register deopt_entry = temps.AcquireX(); | 908 Register deopt_entry = temps.AcquireX(); |
| 906 __ Bind(&call_deopt_entry); | 909 __ Bind(&call_deopt_entry); |
| 907 __ Mov(deopt_entry, Operand(reinterpret_cast<uint64_t>(base), | 910 __ Mov(deopt_entry, Operand(reinterpret_cast<uint64_t>(base), |
| 908 RelocInfo::RUNTIME_ENTRY)); | 911 RelocInfo::RUNTIME_ENTRY)); |
| 909 __ Add(deopt_entry, deopt_entry, entry_offset); | 912 __ Add(deopt_entry, deopt_entry, entry_offset); |
| 910 __ Call(deopt_entry); | 913 |
| 914 const Register& caller_address = entry_offset; | |
| 915 ASSERT(caller_address.Is(ip1)); | |
| 916 __ adr(caller_address, 0); | |
| 917 __ Br(deopt_entry); | |
| 911 } | 918 } |
| 912 | 919 |
| 913 // Force constant pool emission at the end of the deopt jump table to make | 920 // Force constant pool emission at the end of the deopt jump table to make |
| 914 // sure that no constant pools are emitted after. | 921 // sure that no constant pools are emitted after. |
| 915 masm()->CheckConstPool(true, false); | 922 masm()->CheckConstPool(true, false); |
| 916 | 923 |
| 917 // The deoptimization jump table is the last part of the instruction | 924 // The deoptimization jump table is the last part of the instruction |
| 918 // sequence. Mark the generated code as done unless we bailed out. | 925 // sequence. Mark the generated code as done unless we bailed out. |
| 919 if (!is_aborted()) status_ = DONE; | 926 if (!is_aborted()) status_ = DONE; |
| 920 return !is_aborted(); | 927 return !is_aborted(); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1029 __ Push(x0, x1, x2); | 1036 __ Push(x0, x1, x2); |
| 1030 __ Mrs(x2, NZCV); | 1037 __ Mrs(x2, NZCV); |
| 1031 __ Mov(x0, count); | 1038 __ Mov(x0, count); |
| 1032 __ Ldr(w1, MemOperand(x0)); | 1039 __ Ldr(w1, MemOperand(x0)); |
| 1033 __ Subs(x1, x1, 1); | 1040 __ Subs(x1, x1, 1); |
| 1034 __ B(gt, ¬_zero); | 1041 __ B(gt, ¬_zero); |
| 1035 __ Mov(w1, FLAG_deopt_every_n_times); | 1042 __ Mov(w1, FLAG_deopt_every_n_times); |
| 1036 __ Str(w1, MemOperand(x0)); | 1043 __ Str(w1, MemOperand(x0)); |
| 1037 __ Pop(x2, x1, x0); | 1044 __ Pop(x2, x1, x0); |
| 1038 ASSERT(frame_is_built_); | 1045 ASSERT(frame_is_built_); |
| 1039 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 1046 |
| 1047 { | |
| 1048 UseScratchRegisterScope temps(masm()); | |
| 1049 // The second-level deopt table expects the caller address in ip1. | |
| 1050 Register caller_address = temps.Acquire(ip1); | |
| 1051 Register entry_address = temps.AcquireX(); | |
| 1052 | |
| 1053 __ Mov(entry_address, Operand(reinterpret_cast<uintptr_t>(entry), | |
| 1054 RelocInfo::RUNTIME_ENTRY)); | |
| 1055 __ adr(caller_address, 0); | |
| 1056 __ Br(entry_address); | |
| 1057 } | |
| 1058 | |
| 1040 __ Unreachable(); | 1059 __ Unreachable(); |
| 1041 | 1060 |
| 1042 __ Bind(¬_zero); | 1061 __ Bind(¬_zero); |
| 1043 __ Str(w1, MemOperand(x0)); | 1062 __ Str(w1, MemOperand(x0)); |
| 1044 __ Msr(NZCV, x2); | 1063 __ Msr(NZCV, x2); |
| 1045 __ Pop(x2, x1, x0); | 1064 __ Pop(x2, x1, x0); |
| 1046 } | 1065 } |
| 1047 | 1066 |
| 1048 if (info()->ShouldTrapOnDeopt()) { | 1067 if (info()->ShouldTrapOnDeopt()) { |
| 1049 Label dont_trap; | 1068 Label dont_trap; |
| 1050 __ B(&dont_trap, InvertBranchType(branch_type), reg, bit); | 1069 __ B(&dont_trap, InvertBranchType(branch_type), reg, bit); |
| 1051 __ Debug("trap_on_deopt", __LINE__, BREAK); | 1070 __ Debug("trap_on_deopt", __LINE__, BREAK); |
| 1052 __ Bind(&dont_trap); | 1071 __ Bind(&dont_trap); |
| 1053 } | 1072 } |
| 1054 | 1073 |
| 1055 ASSERT(info()->IsStub() || frame_is_built_); | 1074 ASSERT(info()->IsStub() || frame_is_built_); |
| 1056 // Go through jump table if we need to build frame, or restore caller doubles. | |
| 1057 if (branch_type == always && | 1075 if (branch_type == always && |
| 1058 frame_is_built_ && !info()->saves_caller_doubles()) { | 1076 frame_is_built_ && !info()->saves_caller_doubles()) { |
| 1059 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 1077 // For unconditional deopts that don't require special handling (such as |
| 1078 // constructing a frame), branch directly to the second-level table. | |
| 1079 | |
| 1080 UseScratchRegisterScope temps(masm()); | |
| 1081 // The second-level deopt table expects the caller address in ip1. | |
| 1082 Register caller_address = temps.Acquire(ip1); | |
| 1083 Register entry_address = temps.AcquireX(); | |
| 1084 | |
| 1085 __ Mov(entry_address, Operand(reinterpret_cast<uintptr_t>(entry), | |
| 1086 RelocInfo::RUNTIME_ENTRY)); | |
| 1087 __ adr(caller_address, 0); | |
| 1088 __ Br(entry_address); | |
| 1060 } else { | 1089 } else { |
| 1090 // For conditional deopts, try to generate as little fast-path code as | |
| 1091 // possible. Defer all special handling to the first-level deopt table and | |
| 1092 // emit a simple conditional branch here. | |
| 1093 | |
| 1061 // We often have several deopts to the same entry, reuse the last | 1094 // We often have several deopts to the same entry, reuse the last |
| 1062 // jump entry if this is the case. | 1095 // jump entry if this is the case. |
| 1063 if (deopt_jump_table_.is_empty() || | 1096 if (deopt_jump_table_.is_empty() || |
| 1064 (deopt_jump_table_.last()->address != entry) || | 1097 (deopt_jump_table_.last()->address != entry) || |
| 1065 (deopt_jump_table_.last()->bailout_type != bailout_type) || | 1098 (deopt_jump_table_.last()->bailout_type != bailout_type) || |
| 1066 (deopt_jump_table_.last()->needs_frame != !frame_is_built_)) { | 1099 (deopt_jump_table_.last()->needs_frame != !frame_is_built_)) { |
| 1067 Deoptimizer::JumpTableEntry* table_entry = | 1100 Deoptimizer::JumpTableEntry* table_entry = |
| 1068 new(zone()) Deoptimizer::JumpTableEntry(entry, | 1101 new(zone()) Deoptimizer::JumpTableEntry(entry, |
| 1069 bailout_type, | 1102 bailout_type, |
| 1070 !frame_is_built_); | 1103 !frame_is_built_); |
| (...skipping 4981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6052 Handle<ScopeInfo> scope_info = instr->scope_info(); | 6085 Handle<ScopeInfo> scope_info = instr->scope_info(); |
| 6053 __ Push(scope_info); | 6086 __ Push(scope_info); |
| 6054 __ Push(ToRegister(instr->function())); | 6087 __ Push(ToRegister(instr->function())); |
| 6055 CallRuntime(Runtime::kHiddenPushBlockContext, 2, instr); | 6088 CallRuntime(Runtime::kHiddenPushBlockContext, 2, instr); |
| 6056 RecordSafepoint(Safepoint::kNoLazyDeopt); | 6089 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 6057 } | 6090 } |
| 6058 | 6091 |
| 6059 | 6092 |
| 6060 | 6093 |
| 6061 } } // namespace v8::internal | 6094 } } // namespace v8::internal |
| OLD | NEW |