| 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/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 | 6 |
| 7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
| 9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
| 10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 Label done; \ | 330 Label done; \ |
| 331 __ j(above_equal, &done, Label::kNear); \ | 331 __ j(above_equal, &done, Label::kNear); \ |
| 332 if (instr->InputAt(2)->IsRegister()) { \ | 332 if (instr->InputAt(2)->IsRegister()) { \ |
| 333 __ asm_instr(i.MemoryOperand(3), i.InputRegister(2)); \ | 333 __ asm_instr(i.MemoryOperand(3), i.InputRegister(2)); \ |
| 334 } else { \ | 334 } else { \ |
| 335 __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \ | 335 __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \ |
| 336 } \ | 336 } \ |
| 337 __ bind(&done); \ | 337 __ bind(&done); \ |
| 338 } while (false) | 338 } while (false) |
| 339 | 339 |
| 340 void CodeGenerator::AssembleDeconstructFrame() { |
| 341 __ mov(esp, ebp); |
| 342 __ pop(ebp); |
| 343 } |
| 344 |
| 345 // For insert fninit/fld1 instructions after the Prologue |
| 346 thread_local bool is_block_0 = false; |
| 347 |
| 348 void CodeGenerator::AssembleSetupStackPointer() { is_block_0 = true; } |
| 340 | 349 |
| 341 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 350 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { |
| 342 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | 351 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); |
| 343 if (sp_slot_delta > 0) { | 352 if (sp_slot_delta > 0) { |
| 344 __ add(esp, Immediate(sp_slot_delta * kPointerSize)); | 353 __ add(esp, Immediate(sp_slot_delta * kPointerSize)); |
| 345 } | 354 } |
| 346 frame_access_state()->SetFrameAccessToDefault(); | 355 frame_access_state()->SetFrameAccessToDefault(); |
| 347 } | 356 } |
| 348 | 357 |
| 349 | 358 |
| 350 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | 359 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { |
| 351 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | 360 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); |
| 352 if (sp_slot_delta < 0) { | 361 if (sp_slot_delta < 0) { |
| 353 __ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); | 362 __ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); |
| 354 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | 363 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); |
| 355 } | 364 } |
| 356 if (frame()->needs_frame()) { | 365 if (frame_access_state()->has_frame()) { |
| 357 __ mov(ebp, MemOperand(ebp, 0)); | 366 __ mov(ebp, MemOperand(ebp, 0)); |
| 358 } | 367 } |
| 359 frame_access_state()->SetFrameAccessToSP(); | 368 frame_access_state()->SetFrameAccessToSP(); |
| 360 } | 369 } |
| 361 | 370 |
| 362 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, | 371 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
| 363 Register, Register, | 372 Register, Register, |
| 364 Register) { | 373 Register) { |
| 365 // There are not enough temp registers left on ia32 for a call instruction | 374 // There are not enough temp registers left on ia32 for a call instruction |
| 366 // so we pick some scratch registers and save/restore them manually here. | 375 // so we pick some scratch registers and save/restore them manually here. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 395 __ pop(scratch1); | 404 __ pop(scratch1); |
| 396 | 405 |
| 397 __ bind(&done); | 406 __ bind(&done); |
| 398 } | 407 } |
| 399 | 408 |
| 400 // Assembles an instruction after register allocation, producing machine code. | 409 // Assembles an instruction after register allocation, producing machine code. |
| 401 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 410 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
| 402 X87OperandConverter i(this, instr); | 411 X87OperandConverter i(this, instr); |
| 403 InstructionCode opcode = instr->opcode(); | 412 InstructionCode opcode = instr->opcode(); |
| 404 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); | 413 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
| 414 |
| 415 // Workaround for CL #35139 (https://codereview.chromium.org/1775323002) |
| 416 if (is_block_0) { |
| 417 __ fninit(); |
| 418 __ fld1(); |
| 419 is_block_0 = false; |
| 420 } |
| 421 |
| 405 switch (arch_opcode) { | 422 switch (arch_opcode) { |
| 406 case kArchCallCodeObject: { | 423 case kArchCallCodeObject: { |
| 407 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 424 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
| 408 __ VerifyX87StackDepth(1); | 425 __ VerifyX87StackDepth(1); |
| 409 } | 426 } |
| 410 __ fstp(0); | 427 __ fstp(0); |
| 411 EnsureSpaceForLazyDeopt(); | 428 EnsureSpaceForLazyDeopt(); |
| 412 if (HasImmediateInput(instr, 0)) { | 429 if (HasImmediateInput(instr, 0)) { |
| 413 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 430 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
| 414 __ call(code, RelocInfo::CODE_TARGET); | 431 __ call(code, RelocInfo::CODE_TARGET); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 case kArchRet: | 609 case kArchRet: |
| 593 AssembleReturn(); | 610 AssembleReturn(); |
| 594 break; | 611 break; |
| 595 case kArchFramePointer: | 612 case kArchFramePointer: |
| 596 __ mov(i.OutputRegister(), ebp); | 613 __ mov(i.OutputRegister(), ebp); |
| 597 break; | 614 break; |
| 598 case kArchStackPointer: | 615 case kArchStackPointer: |
| 599 __ mov(i.OutputRegister(), esp); | 616 __ mov(i.OutputRegister(), esp); |
| 600 break; | 617 break; |
| 601 case kArchParentFramePointer: | 618 case kArchParentFramePointer: |
| 602 if (frame_access_state()->frame()->needs_frame()) { | 619 if (frame_access_state()->has_frame()) { |
| 603 __ mov(i.OutputRegister(), Operand(ebp, 0)); | 620 __ mov(i.OutputRegister(), Operand(ebp, 0)); |
| 604 } else { | 621 } else { |
| 605 __ mov(i.OutputRegister(), ebp); | 622 __ mov(i.OutputRegister(), ebp); |
| 606 } | 623 } |
| 607 break; | 624 break; |
| 608 case kArchTruncateDoubleToI: { | 625 case kArchTruncateDoubleToI: { |
| 609 if (!instr->InputAt(0)->IsDoubleRegister()) { | 626 if (!instr->InputAt(0)->IsDoubleRegister()) { |
| 610 __ fld_d(i.InputOperand(0)); | 627 __ fld_d(i.InputOperand(0)); |
| 611 } | 628 } |
| 612 __ TruncateX87TOSToI(i.OutputRegister()); | 629 __ TruncateX87TOSToI(i.OutputRegister()); |
| (...skipping 1461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2074 // | FP | RET | args | caller frame | | 2091 // | FP | RET | args | caller frame | |
| 2075 // ^ esp,ebp | 2092 // ^ esp,ebp |
| 2076 | 2093 |
| 2077 // --{ pop ebp }---------------------------------------------------------------- | 2094 // --{ pop ebp }---------------------------------------------------------------- |
| 2078 // | RET | args | caller frame | | 2095 // | RET | args | caller frame | |
| 2079 // ^ esp ^ ebp | 2096 // ^ esp ^ ebp |
| 2080 | 2097 |
| 2081 | 2098 |
| 2082 void CodeGenerator::AssemblePrologue() { | 2099 void CodeGenerator::AssemblePrologue() { |
| 2083 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 2100 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| 2084 if (frame()->needs_frame()) { | 2101 if (frame_access_state()->has_frame()) { |
| 2085 if (descriptor->IsCFunctionCall()) { | 2102 if (descriptor->IsCFunctionCall()) { |
| 2086 __ push(ebp); | 2103 __ push(ebp); |
| 2087 __ mov(ebp, esp); | 2104 __ mov(ebp, esp); |
| 2088 } else if (descriptor->IsJSFunctionCall()) { | 2105 } else if (descriptor->IsJSFunctionCall()) { |
| 2089 __ Prologue(this->info()->GeneratePreagedPrologue()); | 2106 __ Prologue(this->info()->GeneratePreagedPrologue()); |
| 2090 } else { | 2107 } else { |
| 2091 __ StubPrologue(info()->GetOutputStackFrameType()); | 2108 __ StubPrologue(info()->GetOutputStackFrameType()); |
| 2092 } | 2109 } |
| 2093 } else { | |
| 2094 frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize); | |
| 2095 } | 2110 } |
| 2096 frame_access_state()->SetFrameAccessToDefault(); | |
| 2097 | |
| 2098 int stack_shrink_slots = frame()->GetSpillSlotCount(); | 2111 int stack_shrink_slots = frame()->GetSpillSlotCount(); |
| 2099 if (info()->is_osr()) { | 2112 if (info()->is_osr()) { |
| 2100 // TurboFan OSR-compiled functions cannot be entered directly. | 2113 // TurboFan OSR-compiled functions cannot be entered directly. |
| 2101 __ Abort(kShouldNotDirectlyEnterOsrFunction); | 2114 __ Abort(kShouldNotDirectlyEnterOsrFunction); |
| 2102 | 2115 |
| 2103 // Unoptimized code jumps directly to this entrypoint while the unoptimized | 2116 // Unoptimized code jumps directly to this entrypoint while the unoptimized |
| 2104 // frame is still on the stack. Optimized code uses OSR values directly from | 2117 // frame is still on the stack. Optimized code uses OSR values directly from |
| 2105 // the unoptimized frame. Thus, all that needs to be done is to allocate the | 2118 // the unoptimized frame. Thus, all that needs to be done is to allocate the |
| 2106 // remaining stack slots. | 2119 // remaining stack slots. |
| 2107 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); | 2120 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); |
| 2108 osr_pc_offset_ = __ pc_offset(); | 2121 osr_pc_offset_ = __ pc_offset(); |
| 2109 stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots(); | 2122 stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots(); |
| 2123 |
| 2124 // Initailize FPU state. |
| 2125 __ fninit(); |
| 2126 __ fld1(); |
| 2110 } | 2127 } |
| 2111 | 2128 |
| 2112 const RegList saves = descriptor->CalleeSavedRegisters(); | 2129 const RegList saves = descriptor->CalleeSavedRegisters(); |
| 2113 if (stack_shrink_slots > 0) { | 2130 if (stack_shrink_slots > 0) { |
| 2114 __ sub(esp, Immediate(stack_shrink_slots * kPointerSize)); | 2131 __ sub(esp, Immediate(stack_shrink_slots * kPointerSize)); |
| 2115 } | 2132 } |
| 2116 | 2133 |
| 2117 if (saves != 0) { // Save callee-saved registers. | 2134 if (saves != 0) { // Save callee-saved registers. |
| 2118 DCHECK(!info()->is_osr()); | 2135 DCHECK(!info()->is_osr()); |
| 2119 int pushed = 0; | 2136 int pushed = 0; |
| 2120 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { | 2137 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { |
| 2121 if (!((1 << i) & saves)) continue; | 2138 if (!((1 << i) & saves)) continue; |
| 2122 __ push(Register::from_code(i)); | 2139 __ push(Register::from_code(i)); |
| 2123 ++pushed; | 2140 ++pushed; |
| 2124 } | 2141 } |
| 2125 frame()->AllocateSavedCalleeRegisterSlots(pushed); | 2142 frame()->AllocateSavedCalleeRegisterSlots(pushed); |
| 2126 } | 2143 } |
| 2127 | |
| 2128 // Initailize FPU state. | |
| 2129 __ fninit(); | |
| 2130 __ fld1(); | |
| 2131 } | 2144 } |
| 2132 | 2145 |
| 2133 | 2146 |
| 2134 void CodeGenerator::AssembleReturn() { | 2147 void CodeGenerator::AssembleReturn() { |
| 2135 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 2148 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| 2136 | 2149 |
| 2137 // Clear the FPU stack only if there is no return value in the stack. | 2150 // Clear the FPU stack only if there is no return value in the stack. |
| 2138 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 2151 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
| 2139 __ VerifyX87StackDepth(1); | 2152 __ VerifyX87StackDepth(1); |
| 2140 } | 2153 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2153 const RegList saves = descriptor->CalleeSavedRegisters(); | 2166 const RegList saves = descriptor->CalleeSavedRegisters(); |
| 2154 // Restore registers. | 2167 // Restore registers. |
| 2155 if (saves != 0) { | 2168 if (saves != 0) { |
| 2156 for (int i = 0; i < Register::kNumRegisters; i++) { | 2169 for (int i = 0; i < Register::kNumRegisters; i++) { |
| 2157 if (!((1 << i) & saves)) continue; | 2170 if (!((1 << i) & saves)) continue; |
| 2158 __ pop(Register::from_code(i)); | 2171 __ pop(Register::from_code(i)); |
| 2159 } | 2172 } |
| 2160 } | 2173 } |
| 2161 | 2174 |
| 2162 if (descriptor->IsCFunctionCall()) { | 2175 if (descriptor->IsCFunctionCall()) { |
| 2163 __ mov(esp, ebp); // Move stack pointer back to frame pointer. | 2176 AssembleDeconstructFrame(); |
| 2164 __ pop(ebp); // Pop caller's frame pointer. | 2177 } else if (frame_access_state()->has_frame()) { |
| 2165 } else if (frame()->needs_frame()) { | |
| 2166 // Canonicalize JSFunction return sites for now. | 2178 // Canonicalize JSFunction return sites for now. |
| 2167 if (return_label_.is_bound()) { | 2179 if (return_label_.is_bound()) { |
| 2168 __ jmp(&return_label_); | 2180 __ jmp(&return_label_); |
| 2169 return; | 2181 return; |
| 2170 } else { | 2182 } else { |
| 2171 __ bind(&return_label_); | 2183 __ bind(&return_label_); |
| 2172 __ mov(esp, ebp); // Move stack pointer back to frame pointer. | 2184 AssembleDeconstructFrame(); |
| 2173 __ pop(ebp); // Pop caller's frame pointer. | |
| 2174 } | 2185 } |
| 2175 } | 2186 } |
| 2176 if (pop_count == 0) { | 2187 if (pop_count == 0) { |
| 2177 __ ret(0); | 2188 __ ret(0); |
| 2178 } else { | 2189 } else { |
| 2179 __ Ret(pop_count * kPointerSize, ebx); | 2190 __ Ret(pop_count * kPointerSize, ebx); |
| 2180 } | 2191 } |
| 2181 } | 2192 } |
| 2182 | 2193 |
| 2183 | 2194 |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2416 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2427 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
| 2417 __ Nop(padding_size); | 2428 __ Nop(padding_size); |
| 2418 } | 2429 } |
| 2419 } | 2430 } |
| 2420 | 2431 |
| 2421 #undef __ | 2432 #undef __ |
| 2422 | 2433 |
| 2423 } // namespace compiler | 2434 } // namespace compiler |
| 2424 } // namespace internal | 2435 } // namespace internal |
| 2425 } // namespace v8 | 2436 } // namespace v8 |
| OLD | NEW |