| 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 382 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 393     __ fstp_d(Operand(esp, 0));                                               \ | 393     __ fstp_d(Operand(esp, 0));                                               \ | 
| 394     __ movsd(i.OutputDoubleRegister(), Operand(esp, 0));                      \ | 394     __ movsd(i.OutputDoubleRegister(), Operand(esp, 0));                      \ | 
| 395     __ add(esp, Immediate(kDoubleSize));                                      \ | 395     __ add(esp, Immediate(kDoubleSize));                                      \ | 
| 396   } while (false) | 396   } while (false) | 
| 397 | 397 | 
| 398 void CodeGenerator::AssembleDeconstructFrame() { | 398 void CodeGenerator::AssembleDeconstructFrame() { | 
| 399   __ mov(esp, ebp); | 399   __ mov(esp, ebp); | 
| 400   __ pop(ebp); | 400   __ pop(ebp); | 
| 401 } | 401 } | 
| 402 | 402 | 
| 403 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 403 void CodeGenerator::AssemblePrepareTailCall() { | 
| 404   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); |  | 
| 405   if (sp_slot_delta > 0) { |  | 
| 406     __ add(esp, Immediate(sp_slot_delta * kPointerSize)); |  | 
| 407   } |  | 
| 408   frame_access_state()->SetFrameAccessToDefault(); |  | 
| 409 } |  | 
| 410 |  | 
| 411 |  | 
| 412 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { |  | 
| 413   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); |  | 
| 414   if (sp_slot_delta < 0) { |  | 
| 415     __ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); |  | 
| 416     frame_access_state()->IncreaseSPDelta(-sp_slot_delta); |  | 
| 417   } |  | 
| 418   if (frame_access_state()->has_frame()) { | 404   if (frame_access_state()->has_frame()) { | 
| 419     __ mov(ebp, MemOperand(ebp, 0)); | 405     __ mov(ebp, MemOperand(ebp, 0)); | 
| 420   } | 406   } | 
| 421   frame_access_state()->SetFrameAccessToSP(); | 407   frame_access_state()->SetFrameAccessToSP(); | 
| 422 } | 408 } | 
| 423 | 409 | 
| 424 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, | 410 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, | 
| 425                                                      Register, Register, | 411                                                      Register, Register, | 
| 426                                                      Register) { | 412                                                      Register) { | 
| 427   // There are not enough temp registers left on ia32 for a call instruction | 413   // There are not enough temp registers left on ia32 for a call instruction | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 452   ParameterCount callee_args_count(args_reg); | 438   ParameterCount callee_args_count(args_reg); | 
| 453   __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, | 439   __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, | 
| 454                         scratch3, ReturnAddressState::kOnStack, scratch_count); | 440                         scratch3, ReturnAddressState::kOnStack, scratch_count); | 
| 455   __ pop(scratch3); | 441   __ pop(scratch3); | 
| 456   __ pop(scratch2); | 442   __ pop(scratch2); | 
| 457   __ pop(scratch1); | 443   __ pop(scratch1); | 
| 458 | 444 | 
| 459   __ bind(&done); | 445   __ bind(&done); | 
| 460 } | 446 } | 
| 461 | 447 | 
|  | 448 namespace { | 
|  | 449 void AdjustStackPointerForGap(MacroAssembler* masm, FrameAccessState* state, | 
|  | 450                               int new_slot_above_sp, | 
|  | 451                               bool allow_shrinkage = true) { | 
|  | 452   int current_sp_offset = state->GetSPToFPSlotCount() + | 
|  | 453                           StandardFrameConstants::kFixedSlotCountAboveFp; | 
|  | 454   int stack_slot_delta = new_slot_above_sp - current_sp_offset; | 
|  | 455   if (stack_slot_delta > 0) { | 
|  | 456     masm->sub(esp, Immediate(stack_slot_delta * kPointerSize)); | 
|  | 457     state->IncreaseSPDelta(stack_slot_delta); | 
|  | 458   } else if (allow_shrinkage && stack_slot_delta < 0) { | 
|  | 459     masm->add(esp, Immediate(-stack_slot_delta * kPointerSize)); | 
|  | 460     state->IncreaseSPDelta(stack_slot_delta); | 
|  | 461   } | 
|  | 462 } | 
|  | 463 }  // namespace | 
|  | 464 | 
|  | 465 void CodeGenerator::AssemblePreGaps(Instruction* instr) { | 
|  | 466   int first_unused_stack_slot; | 
|  | 467   if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; | 
|  | 468 | 
|  | 469   GapResolver::PushTypeFlags flags = GapResolver::kImmediatePush; | 
|  | 470   flags |= GapResolver::kScalarPush; | 
|  | 471   ZoneVector<MoveOperands*> pushes(zone()); | 
|  | 472   resolver()->GetPushCompatibleMoves(zone(), instr, flags, &pushes); | 
|  | 473 | 
|  | 474   if (pushes.size() > 0 && | 
|  | 475       (LocationOperand::cast(pushes.back()->destination()).index() + 1 == | 
|  | 476        first_unused_stack_slot)) { | 
|  | 477     IA32OperandConverter g(this, instr); | 
|  | 478     for (auto move : pushes) { | 
|  | 479       LocationOperand destination_location( | 
|  | 480           LocationOperand::cast(move->destination())); | 
|  | 481       InstructionOperand source(move->source()); | 
|  | 482       AdjustStackPointerForGap(masm(), frame_access_state(), | 
|  | 483                                destination_location.index()); | 
|  | 484       if (source.IsStackSlot()) { | 
|  | 485         LocationOperand source_location(LocationOperand::cast(source)); | 
|  | 486         __ push(g.SlotToOperand(source_location.index())); | 
|  | 487         frame_access_state()->IncreaseSPDelta(1); | 
|  | 488         move->Eliminate(); | 
|  | 489       } else if (source.IsRegister()) { | 
|  | 490         LocationOperand source_location(LocationOperand::cast(source)); | 
|  | 491         __ push(source_location.GetRegister()); | 
|  | 492         frame_access_state()->IncreaseSPDelta(1); | 
|  | 493         move->Eliminate(); | 
|  | 494       } else if (source.IsImmediate()) { | 
|  | 495         __ push(Immediate(ImmediateOperand::cast(source).inline_value())); | 
|  | 496         frame_access_state()->IncreaseSPDelta(1); | 
|  | 497         move->Eliminate(); | 
|  | 498       } else { | 
|  | 499         // Pushes of non-scalar data types is not supported. | 
|  | 500         UNIMPLEMENTED(); | 
|  | 501       } | 
|  | 502     } | 
|  | 503   } | 
|  | 504   AdjustStackPointerForGap(masm(), frame_access_state(), | 
|  | 505                            first_unused_stack_slot, false); | 
|  | 506 } | 
|  | 507 | 
|  | 508 void CodeGenerator::AssemblePostGaps(Instruction* instr) { | 
|  | 509   int first_unused_stack_slot; | 
|  | 510   if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; | 
|  | 511   AdjustStackPointerForGap(masm(), frame_access_state(), | 
|  | 512                            first_unused_stack_slot); | 
|  | 513 } | 
|  | 514 | 
| 462 // Assembles an instruction after register allocation, producing machine code. | 515 // Assembles an instruction after register allocation, producing machine code. | 
| 463 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 516 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 
| 464     Instruction* instr) { | 517     Instruction* instr) { | 
| 465   IA32OperandConverter i(this, instr); | 518   IA32OperandConverter i(this, instr); | 
| 466   InstructionCode opcode = instr->opcode(); | 519   InstructionCode opcode = instr->opcode(); | 
| 467   ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); | 520   ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); | 
| 468   switch (arch_opcode) { | 521   switch (arch_opcode) { | 
| 469     case kArchCallCodeObject: { | 522     case kArchCallCodeObject: { | 
| 470       EnsureSpaceForLazyDeopt(); | 523       EnsureSpaceForLazyDeopt(); | 
| 471       if (HasImmediateInput(instr, 0)) { | 524       if (HasImmediateInput(instr, 0)) { | 
| 472         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 525         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 
| 473         __ call(code, RelocInfo::CODE_TARGET); | 526         __ call(code, RelocInfo::CODE_TARGET); | 
| 474       } else { | 527       } else { | 
| 475         Register reg = i.InputRegister(0); | 528         Register reg = i.InputRegister(0); | 
| 476         __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 529         __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 
| 477         __ call(reg); | 530         __ call(reg); | 
| 478       } | 531       } | 
| 479       RecordCallPosition(instr); | 532       RecordCallPosition(instr); | 
| 480       frame_access_state()->ClearSPDelta(); | 533       frame_access_state()->ClearSPDelta(); | 
| 481       break; | 534       break; | 
| 482     } | 535     } | 
| 483     case kArchTailCallCodeObjectFromJSFunction: | 536     case kArchTailCallCodeObjectFromJSFunction: | 
| 484     case kArchTailCallCodeObject: { | 537     case kArchTailCallCodeObject: { | 
| 485       int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |  | 
| 486       AssembleDeconstructActivationRecord(stack_param_delta); |  | 
| 487       if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { | 538       if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { | 
| 488         AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 539         AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 
| 489                                          no_reg, no_reg, no_reg); | 540                                          no_reg, no_reg, no_reg); | 
| 490       } | 541       } | 
| 491       if (HasImmediateInput(instr, 0)) { | 542       if (HasImmediateInput(instr, 0)) { | 
| 492         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 543         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 
| 493         __ jmp(code, RelocInfo::CODE_TARGET); | 544         __ jmp(code, RelocInfo::CODE_TARGET); | 
| 494       } else { | 545       } else { | 
| 495         Register reg = i.InputRegister(0); | 546         Register reg = i.InputRegister(0); | 
| 496         __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 547         __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 
| 497         __ jmp(reg); | 548         __ jmp(reg); | 
| 498       } | 549       } | 
| 499       frame_access_state()->ClearSPDelta(); | 550       frame_access_state()->ClearSPDelta(); | 
|  | 551       frame_access_state()->SetFrameAccessToDefault(); | 
| 500       break; | 552       break; | 
| 501     } | 553     } | 
| 502     case kArchTailCallAddress: { | 554     case kArchTailCallAddress: { | 
| 503       int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |  | 
| 504       AssembleDeconstructActivationRecord(stack_param_delta); |  | 
| 505       CHECK(!HasImmediateInput(instr, 0)); | 555       CHECK(!HasImmediateInput(instr, 0)); | 
| 506       Register reg = i.InputRegister(0); | 556       Register reg = i.InputRegister(0); | 
| 507       __ jmp(reg); | 557       __ jmp(reg); | 
| 508       frame_access_state()->ClearSPDelta(); | 558       frame_access_state()->ClearSPDelta(); | 
|  | 559       frame_access_state()->SetFrameAccessToDefault(); | 
| 509       break; | 560       break; | 
| 510     } | 561     } | 
| 511     case kArchCallJSFunction: { | 562     case kArchCallJSFunction: { | 
| 512       EnsureSpaceForLazyDeopt(); | 563       EnsureSpaceForLazyDeopt(); | 
| 513       Register func = i.InputRegister(0); | 564       Register func = i.InputRegister(0); | 
| 514       if (FLAG_debug_code) { | 565       if (FLAG_debug_code) { | 
| 515         // Check the function's context matches the context argument. | 566         // Check the function's context matches the context argument. | 
| 516         __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 567         __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 
| 517         __ Assert(equal, kWrongFunctionContext); | 568         __ Assert(equal, kWrongFunctionContext); | 
| 518       } | 569       } | 
| 519       __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 570       __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 
| 520       RecordCallPosition(instr); | 571       RecordCallPosition(instr); | 
| 521       frame_access_state()->ClearSPDelta(); | 572       frame_access_state()->ClearSPDelta(); | 
| 522       break; | 573       break; | 
| 523     } | 574     } | 
| 524     case kArchTailCallJSFunctionFromJSFunction: | 575     case kArchTailCallJSFunctionFromJSFunction: | 
| 525     case kArchTailCallJSFunction: { | 576     case kArchTailCallJSFunction: { | 
| 526       Register func = i.InputRegister(0); | 577       Register func = i.InputRegister(0); | 
| 527       if (FLAG_debug_code) { | 578       if (FLAG_debug_code) { | 
| 528         // Check the function's context matches the context argument. | 579         // Check the function's context matches the context argument. | 
| 529         __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 580         __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 
| 530         __ Assert(equal, kWrongFunctionContext); | 581         __ Assert(equal, kWrongFunctionContext); | 
| 531       } | 582       } | 
| 532       int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |  | 
| 533       AssembleDeconstructActivationRecord(stack_param_delta); |  | 
| 534       if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { | 583       if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { | 
| 535         AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 584         AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 
| 536                                          no_reg, no_reg, no_reg); | 585                                          no_reg, no_reg, no_reg); | 
| 537       } | 586       } | 
| 538       __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 587       __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 
| 539       frame_access_state()->ClearSPDelta(); | 588       frame_access_state()->ClearSPDelta(); | 
|  | 589       frame_access_state()->SetFrameAccessToDefault(); | 
| 540       break; | 590       break; | 
| 541     } | 591     } | 
| 542     case kArchPrepareCallCFunction: { | 592     case kArchPrepareCallCFunction: { | 
| 543       // Frame alignment requires using FP-relative frame addressing. | 593       // Frame alignment requires using FP-relative frame addressing. | 
| 544       frame_access_state()->SetFrameAccessToFP(); | 594       frame_access_state()->SetFrameAccessToFP(); | 
| 545       int const num_parameters = MiscField::decode(instr->opcode()); | 595       int const num_parameters = MiscField::decode(instr->opcode()); | 
| 546       __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); | 596       __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); | 
| 547       break; | 597       break; | 
| 548     } | 598     } | 
| 549     case kArchPrepareTailCall: | 599     case kArchPrepareTailCall: | 
| 550       AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); | 600       AssemblePrepareTailCall(); | 
| 551       break; | 601       break; | 
| 552     case kArchCallCFunction: { | 602     case kArchCallCFunction: { | 
| 553       int const num_parameters = MiscField::decode(instr->opcode()); | 603       int const num_parameters = MiscField::decode(instr->opcode()); | 
| 554       if (HasImmediateInput(instr, 0)) { | 604       if (HasImmediateInput(instr, 0)) { | 
| 555         ExternalReference ref = i.InputExternalReference(0); | 605         ExternalReference ref = i.InputExternalReference(0); | 
| 556         __ CallCFunction(ref, num_parameters); | 606         __ CallCFunction(ref, num_parameters); | 
| 557       } else { | 607       } else { | 
| 558         Register func = i.InputRegister(0); | 608         Register func = i.InputRegister(0); | 
| 559         __ CallCFunction(func, num_parameters); | 609         __ CallCFunction(func, num_parameters); | 
| 560       } | 610       } | 
| (...skipping 1491 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2052     int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2102     int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 
| 2053     __ Nop(padding_size); | 2103     __ Nop(padding_size); | 
| 2054   } | 2104   } | 
| 2055 } | 2105 } | 
| 2056 | 2106 | 
| 2057 #undef __ | 2107 #undef __ | 
| 2058 | 2108 | 
| 2059 }  // namespace compiler | 2109 }  // namespace compiler | 
| 2060 }  // namespace internal | 2110 }  // namespace internal | 
| 2061 }  // namespace v8 | 2111 }  // namespace v8 | 
| OLD | NEW | 
|---|