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 "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
10 #include "codegen.h" | 10 #include "codegen.h" |
(...skipping 5002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5013 | 5013 |
5014 TmpList()->set_list(old_tmp_list); | 5014 TmpList()->set_list(old_tmp_list); |
5015 FPTmpList()->set_list(old_fp_tmp_list); | 5015 FPTmpList()->set_list(old_fp_tmp_list); |
5016 } | 5016 } |
5017 | 5017 |
5018 | 5018 |
5019 void MacroAssembler::EmitFrameSetupForCodeAgePatching() { | 5019 void MacroAssembler::EmitFrameSetupForCodeAgePatching() { |
5020 // TODO(jbramley): Other architectures use the internal memcpy to copy the | 5020 // TODO(jbramley): Other architectures use the internal memcpy to copy the |
5021 // sequence. If this is a performance bottleneck, we should consider caching | 5021 // sequence. If this is a performance bottleneck, we should consider caching |
5022 // the sequence and copying it in the same way. | 5022 // the sequence and copying it in the same way. |
5023 InstructionAccurateScope scope(this, kCodeAgeSequenceSize / kInstructionSize); | 5023 InstructionAccurateScope scope(this, |
5024 kNoCodeAgeSequenceLength / kInstructionSize); | |
5024 ASSERT(jssp.Is(StackPointer())); | 5025 ASSERT(jssp.Is(StackPointer())); |
5025 EmitFrameSetupForCodeAgePatching(this); | 5026 EmitFrameSetupForCodeAgePatching(this); |
5026 } | 5027 } |
5027 | 5028 |
5028 | 5029 |
5029 | 5030 |
5030 void MacroAssembler::EmitCodeAgeSequence(Code* stub) { | 5031 void MacroAssembler::EmitCodeAgeSequence(Code* stub) { |
5031 InstructionAccurateScope scope(this, kCodeAgeSequenceSize / kInstructionSize); | 5032 InstructionAccurateScope scope(this, |
5033 kNoCodeAgeSequenceLength / kInstructionSize); | |
5032 ASSERT(jssp.Is(StackPointer())); | 5034 ASSERT(jssp.Is(StackPointer())); |
5033 EmitCodeAgeSequence(this, stub); | 5035 EmitCodeAgeSequence(this, stub); |
5034 } | 5036 } |
5035 | 5037 |
5036 | 5038 |
5037 #undef __ | 5039 #undef __ |
5038 #define __ assm-> | 5040 #define __ assm-> |
5039 | 5041 |
5040 | 5042 |
5041 void MacroAssembler::EmitFrameSetupForCodeAgePatching(Assembler * assm) { | 5043 void MacroAssembler::EmitFrameSetupForCodeAgePatching(Assembler * assm) { |
5042 Label start; | 5044 Label start; |
5043 __ bind(&start); | 5045 __ bind(&start); |
5044 | 5046 |
5045 // We can do this sequence using four instructions, but the code ageing | 5047 // We can do this sequence using four instructions, but the code ageing |
5046 // sequence that patches it needs five, so we use the extra space to try to | 5048 // sequence that patches it needs five, so we use the extra space to try to |
5047 // simplify some addressing modes and remove some dependencies (compared to | 5049 // simplify some addressing modes and remove some dependencies (compared to |
5048 // using two stp instructions with write-back). | 5050 // using two stp instructions with write-back). |
5049 __ sub(jssp, jssp, 4 * kXRegSize); | 5051 __ sub(jssp, jssp, 4 * kXRegSize); |
5050 __ sub(csp, csp, 4 * kXRegSize); | 5052 __ sub(csp, csp, 4 * kXRegSize); |
5051 __ stp(x1, cp, MemOperand(jssp, 0 * kXRegSize)); | 5053 __ stp(x1, cp, MemOperand(jssp, 0 * kXRegSize)); |
5052 __ stp(fp, lr, MemOperand(jssp, 2 * kXRegSize)); | 5054 __ stp(fp, lr, MemOperand(jssp, 2 * kXRegSize)); |
5053 __ add(fp, jssp, StandardFrameConstants::kFixedFrameSizeFromFp); | 5055 __ add(fp, jssp, StandardFrameConstants::kFixedFrameSizeFromFp); |
5054 | 5056 |
5055 __ AssertSizeOfCodeGeneratedSince(&start, kCodeAgeSequenceSize); | 5057 __ AssertSizeOfCodeGeneratedSince(&start, kNoCodeAgeSequenceLength); |
5056 } | 5058 } |
5057 | 5059 |
5058 | 5060 |
5059 void MacroAssembler::EmitCodeAgeSequence(Assembler * assm, | 5061 void MacroAssembler::EmitCodeAgeSequence(Assembler * assm, |
5060 Code * stub) { | 5062 Code * stub) { |
5061 Label start; | 5063 Label start; |
5062 __ bind(&start); | 5064 __ bind(&start); |
5063 // When the stub is called, the sequence is replaced with the young sequence | 5065 // When the stub is called, the sequence is replaced with the young sequence |
5064 // (as in EmitFrameSetupForCodeAgePatching). After the code is replaced, the | 5066 // (as in EmitFrameSetupForCodeAgePatching). After the code is replaced, the |
5065 // stub jumps to &start, stored in x0. The young sequence does not call the | 5067 // stub jumps to &start, stored in x0. The young sequence does not call the |
5066 // stub so there is no infinite loop here. | 5068 // stub so there is no infinite loop here. |
5067 // | 5069 // |
5068 // A branch (br) is used rather than a call (blr) because this code replaces | 5070 // A branch (br) is used rather than a call (blr) because this code replaces |
5069 // the frame setup code that would normally preserve lr. | 5071 // the frame setup code that would normally preserve lr. |
5070 __ LoadLiteral(ip0, kCodeAgeStubEntryOffset); | 5072 __ LoadLiteral(ip0, kCodeAgeStubEntryOffset); |
5071 __ adr(x0, &start); | 5073 __ adr(x0, &start); |
5072 __ br(ip0); | 5074 __ br(ip0); |
5073 // IsCodeAgeSequence in codegen-arm64.cc assumes that the code generated up | 5075 // IsCodeAgeSequence in codegen-arm64.cc assumes that the code generated up |
5074 // until now (kCodeAgeStubEntryOffset) is the same for all code age sequences. | 5076 // until now (kCodeAgeStubEntryOffset) is the same for all code age sequences. |
5075 __ AssertSizeOfCodeGeneratedSince(&start, kCodeAgeStubEntryOffset); | 5077 __ AssertSizeOfCodeGeneratedSince(&start, kCodeAgeStubEntryOffset); |
5076 if (stub) { | 5078 if (stub) { |
5077 __ dc64(reinterpret_cast<uint64_t>(stub->instruction_start())); | 5079 __ dc64(reinterpret_cast<uint64_t>(stub->instruction_start())); |
5078 __ AssertSizeOfCodeGeneratedSince(&start, kCodeAgeSequenceSize); | 5080 __ AssertSizeOfCodeGeneratedSince(&start, kNoCodeAgeSequenceLength); |
5079 } | 5081 } |
5080 } | 5082 } |
5081 | 5083 |
5082 | 5084 |
5083 bool MacroAssembler::IsYoungSequence(byte* sequence) { | 5085 bool MacroAssembler::IsYoungSequence(Isolate* isolate, byte* sequence) { |
5084 // Generate a young sequence to compare with. | 5086 bool is_young = isolate->no_code_age_sequence()->Match(sequence); |
5085 const int length = kCodeAgeSequenceSize / kInstructionSize; | |
5086 static bool initialized = false; | |
5087 static byte young[kCodeAgeSequenceSize]; | |
5088 if (!initialized) { | |
5089 PatchingAssembler patcher(young, length); | |
5090 // The young sequence is the frame setup code for FUNCTION code types. It is | |
5091 // generated by FullCodeGenerator::Generate. | |
5092 MacroAssembler::EmitFrameSetupForCodeAgePatching(&patcher); | |
5093 initialized = true; | |
5094 } | |
5095 | |
5096 bool is_young = (memcmp(sequence, young, kCodeAgeSequenceSize) == 0); | |
5097 ASSERT(is_young || IsCodeAgeSequence(sequence)); | 5087 ASSERT(is_young || IsCodeAgeSequence(sequence)); |
5098 return is_young; | 5088 return is_young; |
5099 } | 5089 } |
5100 | 5090 |
5101 | 5091 |
5102 #ifdef DEBUG | 5092 #ifdef DEBUG |
5103 bool MacroAssembler::IsCodeAgeSequence(byte* sequence) { | 5093 bool MacroAssembler::IsCodeAgeSequence(byte* sequence) { |
5104 // The old sequence varies depending on the code age. However, the code up | 5094 // The old sequence varies depending on the code age. However, the code up |
5105 // until kCodeAgeStubEntryOffset does not change, so we can check that part to | 5095 // until kCodeAgeStubEntryOffset does not change, so we can check that part to |
5106 // get a reasonable level of verification. | 5096 // get a reasonable level of verification. |
5107 const int length = kCodeAgeStubEntryOffset / kInstructionSize; | 5097 const int length = kCodeAgeStubEntryOffset / kInstructionSize; |
5108 static bool initialized = false; | 5098 static bool initialized = false; |
5109 static byte old[kCodeAgeStubEntryOffset]; | 5099 static byte old[kCodeAgeStubEntryOffset]; |
5100 // TODO(mvstanton): this static isn't thread safe. | |
Sven Panne
2014/05/05 07:54:14
Perhaps NoCodeAgeSequence should have a more gener
mvstanton
2014/05/06 09:55:45
I changed it to CodeAgingHelper, and it can determ
| |
5110 if (!initialized) { | 5101 if (!initialized) { |
5111 PatchingAssembler patcher(old, length); | 5102 PatchingAssembler patcher(old, length); |
5112 MacroAssembler::EmitCodeAgeSequence(&patcher, NULL); | 5103 MacroAssembler::EmitCodeAgeSequence(&patcher, NULL); |
5113 initialized = true; | 5104 initialized = true; |
5114 } | 5105 } |
5115 return memcmp(sequence, old, kCodeAgeStubEntryOffset) == 0; | 5106 return memcmp(sequence, old, kCodeAgeStubEntryOffset) == 0; |
5116 } | 5107 } |
5117 #endif | 5108 #endif |
5118 | 5109 |
5119 | 5110 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5215 } | 5206 } |
5216 } | 5207 } |
5217 | 5208 |
5218 | 5209 |
5219 #undef __ | 5210 #undef __ |
5220 | 5211 |
5221 | 5212 |
5222 } } // namespace v8::internal | 5213 } } // namespace v8::internal |
5223 | 5214 |
5224 #endif // V8_TARGET_ARCH_ARM64 | 5215 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |